# @Time : 2021/4/7 16:56
# @Author : Fioman
# @Phone : 13149920693
"""
主要是用来和生产作业相关的控制逻辑写到这里来,简单记为produce
"""
import queue
import threading

import gevent

from eap_control import eap_request, response_parse
from eap_control.data_model import JobCountType, DeviceStatus, AlarmType
from eap_control.eap_config import EapConfig
from eap_control.eap_request import request_alarm_report
from tools import common_tools
from tools.save_image_to_device import *
from tools.send_to_ui_tools import *
from vision_process.cutter_image_deal import *
from vision_process.image_process_4 import *
from vision_process.image_process_6 import get_line_offset_6p, get_boxes_6p, get_size_check_result_6p, get_lines_with_boxes_6p

cp = ConfigParams()
ec = EapConfig()


class ProduceHandler(object):
    """
    生产作业相关的类,这个类主要是用来和正常的生产作业流程去控制的类.
    """

    def __init__(self, imageJoint, bigCutterCamCal, smallCutterCamCal, camZmc, cbjZmc, bigCutterZmc, smallCutterZmc, deviceStates):
        self.camZmc = camZmc
        self.cbjZmc = cbjZmc
        self.deviceStates = deviceStates
        self.imageJoint = imageJoint
        self.bigCutterCamCal = bigCutterCamCal
        self.smallCutterCamCal = smallCutterCamCal
        self.bigCutterZmc = bigCutterZmc
        self.smallCutterZmc = smallCutterZmc
        # 4个单例的类
        self.db = DbHandler()
        self.logger = HdLogger()
        self.reload_working_info_data()
        self.boardSizeAdjustFlag = False  # 尺寸是否调整的标志位
        self.widthAdjustAfter = 0
        self.heightAdjustAfter = 0
        self.linesQueue = None  # 一开始
        self.reGetImageFlag = False
        self.lotId = ""
        self.eapListener = threading.Thread(target=self.eap_listener, daemon=True)
        self.eapListener.start()

    def eap_listener(self):
        while True:
            # eap工单切换监听
            if settings.eapCanChangeOrderFlag:
                # 接收到工单切换请求
                self.logger.debug("接收到EAP工单切换请求,开始切换工单,将可以切换工单的标志位设置为False")
                # 从Eap队列中获取工单信息
                res, orderList = db.get_lot_command_download_info()
                settings.canChangeOrderFlag = False
                if res != "ok":
                    self.logger.debug("获取工单信息失败,请检查数据库:{}".format(orderList))
                    continue
                # 获取工单信息,看看本地工单时候有对应的工单,如果有就用本地的,如果没有就插入新的工单
                orderInfo = orderList[0]
                query = {
                    "lot_id": orderInfo["lot_id"],
                    "prod_id": orderInfo["prod_id"],
                }
                res, data = self.db.get_data_one(self.db.orderTable, query)
                if res != "ok":
                    newData = {
                        "key": int(time.time() * 1000),
                        "lot_id": orderInfo["lot_id"],
                        "prod_id": orderInfo["prod_id"],
                        "width": orderInfo["width"],
                        "height": orderInfo["height"],
                        "cropperThick": orderInfo["cropperThick"],
                        "joint_number": orderInfo["jointNumber"],
                        "topEdge": orderInfo["leftEdge"],
                        "leftEdge": orderInfo["leftEdge"],
                        "bottomEdge": orderInfo["leftEdge"],
                        "rightEdge": orderInfo["leftEdge"],
                        "planCount": orderInfo["lot_qty"],
                        "finished": 0,
                    }
                    # 插入新的工单,然后进行工单切换
                    self.db.insert_data(self.db.orderTable, newData)
                else:
                    newData = data
                self.order_info_init(newData)
                settings.eapIsInProduce = True
            gevent.sleep(1)

    def produce_prepare_init(self):
        """
        生产作业开始之前的参数初始化,参数的阈值设定参数.
        :return:
        """
        self.linesQueue = queue.Queue()  # 切线队列
        self.cutterQueue = queue.Queue()  # 创建后铡刀的值的队列
        self.cutterQueueSmall = queue.Queue()  # 创建小铡刀的数据队列
        # 上料线阵相机的阈值设定
        self.reload_line_cam_check_thres()
        # 上料面阵相机的阈值设定
        self.reload_cutter_cam_check_thres_big()
        self.reload_cutter_cam_check_thres_small()
        # workingInfo参数的初始化
        self.isAllowGetImage = True  # 是否允许拍照
        self.waitBoardBack = False  # 是否等待板回退
        self.reload_trans_mtx()
        self.reload_cbj_axis_limit()  # 加载裁切机的极限幅面值
        self.cutYAxisOffset = 0  # y轴补偿值

    def reload_cbj_axis_limit(self):
        res, cbjZmcParams = self.db.get_cbj_zmc_params(self.db.cbjZmcParamsTable)
        if res != "ok":
            errorInfo = "in reload_cbj_axis_limit() error: {}".format(cbjZmcParams)
            print(errorInfo)
            self.logger.debug(errorInfo)
        else:
            self.cbjLimitX = cbjZmcParams.get("fx_max")
            self.cbjLimitY = cbjZmcParams.get("fy_max")

    def reload_trans_mtx(self):
        """
        加载标定的矩阵
        :return:
        """
        res, transMtxData = self.db.get_trans_mtx_data()
        self.transMtx = []
        if res != "ok":
            errorInfo = "in reload_trans_mtx() error: {}".format(transMtxData)
            print(errorInfo)
            self.logger.debug(errorInfo)
        else:
            # mtxLeft = transMtxData.get("mtxLeft")
            # mtxRigth = transMtxData.get("mtxRight")
            # self.transMtx.append(mtxLeft)
            self.transMtx = transMtxData.get("transMtx")

    def reload_working_info_data(self):
        """
        重新加载working表的内容.
        :return:
        """
        res, workingInfo = self.db.get_working_info()
        if res == "ok":
            self.camZmcIndex = int(workingInfo.get("camZmcIndex", 0)) + 1  # 拍照控制器的索引,获取旧的,在旧的基础上加1
            self.cbjZmcIndex = self.camZmcIndex
            self.bigCutterZmcIndex = self.camZmcIndex
            self.smallCutterIndex = self.bigCutterZmcIndex
            self.indexMax = 10000
            self.key = workingInfo.get("orderUsedKey")

    def reload_cutter_cam_check_thres_big(self):
        """
        重新加载面阵相机检测的时候使用的阈值
        :return:
        """
        try:
            res, data = self.db.get_big_cutter_cam_check_thres()
            if res == "ok":
                self.beginAngleThresBig = data.get("beginAngleThresBig")
                self.beginAngleOffsetBig = data.get("beginAngleOffsetBig")
                self.cutterMoveOffsetBig = data.get("cutterMoveOffsetBig")
                self.finalFirstBoardThresBig = data.get("finalFirstBoardThresBig")
                self.finalSecondBoardThresBig = data.get("finalSecondBoardThresBig")
                self.finalTotalBoardThresBig = data.get("finalTotalBoardThresBig")
                self.finalFrontAngleBig = data.get("finalFrontAngleBig")
                self.finalBackAngleBig = data.get("finalBackAngleBig")
                self.finalFoldThresBig = data.get("finalFoldThresBig", 8)  # 终检叠板阈值
            else:
                errorInfo = data
                print(errorInfo)
                self.logger.debug(errorInfo)
        except Exception as e:
            errorInfo = "in ProduceHandler.reload_cutter_cam_check_thres_big() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)

    def reload_cutter_cam_check_thres_small(self):
        """
        重新加载面阵相机检测的时候使用的阈值
        :return:
        """
        try:
            res, data = self.db.get_small_cutter_cam_check_thres()
            if res == "ok":
                self.beginAngleThresSmall = data.get("beginAngleThresSmall")
                self.beginAngleOffsetSmall = data.get("beginAngleOffsetSmall")
                self.cutterMoveOffsetSmall = data.get("cutterMoveOffsetSmall")
                self.finalFirstBoardThresSmall = data.get("finalFirstBoardThresSmall")
                self.finalSecondBoardThresSmall = data.get("finalSecondBoardThresSmall")
                self.finalTotalBoardThresSmall = data.get("finalTotalBoardThresSmall")
                self.finalFrontAngleSmall = data.get("finalFrontAngleSmall")
                self.finalBackAngleSmall = data.get("finalBackAngleSmall")
                self.finalFoldThresSmall = data.get("finalFoldThresSmall", 8)  # 终检叠板阈值
                self.twoCutterAngleOffset = data.get("twoCutterAngleOffset", 0)  # 两个铡刀平面之间的补偿角度
            else:
                errorInfo = data
                print(errorInfo)
                self.logger.debug(errorInfo)
        except Exception as e:
            errorInfo = "in ProduceHandler.reload_cutter_cam_check_thres_small() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)

    def reload_line_cam_check_thres(self):
        """
        重新加载线阵相机使用的阈值
        :return:
        """
        try:
            res, data = self.db.get_line_cam_check_thres()
            if res == "ok":
                self.totalHeightMax = data.get("totalHeightMax")
                self.totalHeightMin = data.get("totalHeightMin")
                self.calcThresBig = data.get("calcThresBig")
                self.calcThresSmall = data.get("calcThresSmall")
                self.innerToEdgeThres = data.get("innerToEdgeThres")
                self.firstBoardErrorThres = data.get("firstBoardErrorThres")
                self.secondBoardErrorThres = data.get("secondBoardErrorThres")
                self.totalBoardErrorThres = data.get("totalBoardErrorThres")
            else:
                errorInfo = data
                print(errorInfo)
                self.logger.debug(errorInfo)
        except Exception as e:
            errorInfo = "in ProduceHandler.line_cam_check_thres_reload() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)

    @staticmethod
    def reload_config_params():
        """
        重新初始化加载相机参数
        :return:
        """
        # 重新加载那些全局的参数
        cp.reload_config_params()

    # web_request_函数,下面全部都是.
    def web_request_login(self, userInfo):
        """
        前端界面请求登陆界面.
        :param userInfo:用户信息,包含用户名和密码
        :return:
        """
        username = userInfo.get("username", "")
        password = userInfo.get("password", "")

        if username == 'admin' and password == 'hengdingNo.1':
            res = {
                'currentAuthority': 'admin',
                'status': 'ok',
                'type': 'account'
            }
            self.db.update_login_state(True)
            return res
        userInfo = self.db.get_user_list_by_username(username)
        if len(userInfo) == 0:
            res = {
                'status': 'error',
                'errorMsg': '你输入的用户名不存在,请重新输入'
            }
            return res
        elif username == "" and password == "":
            res = {
                'status': 'error',
                'errorMsg': '输入的用户名和密码不能是空,请重新输入'
            }
            return res
        elif username != userInfo.get("username", "") or password != userInfo.get("password", ""):
            res = {
                'currentAuthority': 'guest',
                'status': 'error',
                'errorMsg': '你输入的密码错误,请重新输入',
                'type': 'account'
            }
            return res
        else:
            if userInfo.get("role", "") == "普通用户":
                res = {
                    'currentAuthority': "user",
                    'status': "ok",
                    'type': "account"
                }
            else:
                res = {
                    'currentAuthority': "serviceman",
                    'status': "ok",
                    'type': "account"
                }

            # 登录成功,刷新登录时间.
            query = {
                "username": username
            }
            tableName = "userinfo"
            newValues = {
                "$set": {
                    "lastLoginTime": common_tools.get_time_now_string()
                }
            }
            self.db.update_data(tableName, query, newValues)

            # 更新登录状态
            self.db.update_login_state(True)
            return res

    def web_request_get_line_cam_check_thres(self):
        """
        前端界面请求线阵相机识别参数阈值.
        :return:
        """
        res, data = self.db.get_line_cam_check_thres()
        return [data] if res == "ok" else []

    def web_request_save_line_cam_check_thres(self, newData):
        """
        前端界面请求保存线阵相机检测参数阈值
        :param newData: 新的参数
        :return:
        """
        res, info = self.db.save_line_cam_check_thres(newData)
        self.reload_line_cam_check_thres()  # 参数重新加载
        return res if res == "ok" else info

    def web_request_get_cutter_cam_check_thres_big(self):
        """
        前端界面请求面阵相机识别参数阈值
        :return:
        """
        res, data = self.db.get_big_cutter_cam_check_thres()
        return [data] if res == "ok" else []

    def web_request_save_cutter_cam_check_thres_big(self, newData):
        """
        前端界面请求保存面阵相机检测阈值
        :param newData:
        :return:
        """
        res, info = self.db.save_big_cutter_cam_check_thres(newData)
        self.reload_cutter_cam_check_thres_big()
        return res if res == "ok" else info

    def web_request_get_cutter_cam_check_thres_small(self):
        """
        前端界面请求面阵相机识别参数阈值
        :return:
        """
        res, data = self.db.get_small_cutter_cam_check_thres()
        return [data] if res == "ok" else []

    def web_request_save_cutter_cam_check_thres_small(self, newData):
        """
        前端界面请求保存面阵相机检测阈值
        :param newData:
        :return:
        """
        res, info = self.db.save_small_cutter_cam_check_thres(newData)
        self.reload_cutter_cam_check_thres_big()
        return res if res == "ok" else info

    def web_request_save_config_params(self, newData):
        """
        前端界面请求保存线阵相机的全局参数值configParams
        :param newData: 新的值
        :return:
        """
        res, info = self.db.save_config_params(newData)
        self.reload_config_params()
        return res if res == "ok" else info

    def order_info_init(self, orderInfo):
        """
        点击自动作业开始的时候工单尺寸初始化
        :param orderInfo: 界面上传递过来的工单信息
        :return:
        """
        self.isFirstBoard = True
        self.boardBreak = True if (orderInfo.get("is_broken", "否") == "是" or
                                   orderInfo.get("is_broken", "NO") == "Yes") else False

        lotId = orderInfo.get("lot_id", "")  # 批号
        if lotId != self.lotId:
            self.lotId = lotId
            ec.realStatusData.lotId = lotId
            res, queueLotCount = db.get_lot_command_download_info()
            if res == "ok":
                queueCount = len(queueLotCount - 1)
            else:
                queueCount = 0
            ec.realStatusData.queueLotCount = queueCount
        self.prodId = orderInfo.get("prod_id", "")  # 料号
        self.jointNumber = orderInfo.get("joint_number", "4")
        self.planCount = orderInfo.get("planCount", 0)  # 计划数量
        self.finished = orderInfo.get("finished", 0)  # 已完成数量

        # self.haveMiddle = True if orderInfo.get("haveMiddle", "有缝") == "有缝" else False # 是否有中缝,没有用的
        self.firstCutSpeed, self.cutSpeed = self.db.get_cut_speed_by_cropper_thick(orderInfo["cropperThick"])
        res, knifeCutParams = self.db.get_knife_cut_params()
        if res != "ok":
            errorInfo = knifeCutParams
            print(errorInfo)
            self.logger.debug(errorInfo)
            self.cutDeep = 0
        else:
            self.cutDeep = knifeCutParams.get("cutDeep")
        self.key = int(orderInfo["key"])
        self.db.save_order_used_key(int(self.key))
        widthUsed = orderInfo["width"]
        heightUsed = orderInfo["height"]
        if orderInfo.get("lengthUnit", "mm") == "mm":
            self.orderWidthMm = widthUsed
            self.orderHeightMm = heightUsed
        else:
            self.orderWidthMm = widthUsed * 25.4
            self.orderHeightMm = heightUsed * 25.4
        # 更新生产参数,到EapConfig中
        # ec.prod_crop_thickness = str(orderInfo["cropperThick"])
        # ec.prod_width = str(widthUsed)
        # ec.prod_height = str(heightUsed)
        # ec.prod_cut_speed = str(self.cutSpeed)
        # ec.prod_cut_deep = str(self.cutDeep)

        self.widthPix = int(widthUsed * cp.mm2pix)
        self.heightPix = int(heightUsed * cp.mm2pix)
        self.widthMm = widthUsed
        self.heightMm = heightUsed
        topEdge = orderInfo["topEdge"]
        leftEdge = orderInfo["leftEdge"]
        bottomEdge = orderInfo["bottomEdge"]
        rightEdge = orderInfo["rightEdge"]
        self.topPix = int(topEdge * cp.mm2pix)
        self.leftPix = int(leftEdge * cp.mm2pix)
        self.bottomPix = int(bottomEdge * cp.mm2pix)
        self.rightPix = int(rightEdge * cp.mm2pix)
        self.topMm = topEdge
        self.leftMm = leftEdge
        self.bottomMm = bottomEdge
        self.rightMm = rightEdge
        # 然后界面上跟新一次工单信息
        msgVal = {
            "val": self.key
        }
        send_order_state_to_ui(msgVal)
        if self.jointNumber == "4":
            ret = self.bigCutterZmc.set_4pin_flag()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
                return ret
        else:
            ret = self.bigCutterZmc.set_6pin_flag()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
                return ret

    def keep_zmc_read_write_error(self, debugMsg, errorType, boardIndex):
        """
        保存通信异常的消息.发送给前端,前端界面上要提示这些消息,并有停止和复位按钮
        :return:
        """
        if errorType == "camZmc":
            errorMsg = "拍照控制器通信异常," + debugMsg
        elif errorType == "cbjZmc":
            errorMsg = "裁切机控制器通信异常," + debugMsg
        elif errorType == "bigCutterZmc":
            errorMsg = "大铡刀控制器通信异常," + debugMsg
        elif errorType == "cameraError":
            errorMsg = "相机抓取图片异常," + debugMsg
        elif errorType == "smallCutterZmc":
            errorMsg = "小铡刀控制器通信异常," + debugMsg
        else:
            errorMsg = debugMsg
        msgVal = {
            "val": "errorState",
            "errorInfo": errorMsg
        }
        self.logger.debug("id_{} {}".format(boardIndex, errorMsg))
        send_produce_state_to_ui(msgVal)
        # 打开蜂鸣器和灯光亮起来
        self.bigCutterZmc.open_buzzer_alarm()

    def web_request_stop_produce(self):
        """
        界面上点击了停止自动作业.
        :return:
        """
        # 自动作业停止,前端界面上点击了停止自动作业
        self.logger.debug("界面上点击了停止,下发停止动作,退出自动作业.camZmcIndex = {},cbjZmcIndex = {},cutterZmcIndex = {}".format(
            self.camZmcIndex, self.cbjZmcIndex, self.bigCutterZmcIndex))
        self.deviceStates.workStopFlag = True
        # 关闭蜂鸣器叫
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.bigCutterZmc.cutter_zmc_stop()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
            return ret
        return "ok"

    def web_request_reset_big_cutter_self(self):
        """
        界面上点击了大铡刀单独复位按钮
        :return:
        """
        ret = self.bigCutterZmc.cutter_zmc_reset_itself()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
            return ret
        self.bigCutterZmc.close_buzzer_alarm()
        self.finalCheckFlagBig = False
        self.beginCheckModifyBig = False
        self.finalCheckModifyBig = False
        self.beginCheckAdjustFlagBig = False
        self.beginCheckModifyBig = False
        self.handCutBoardFlagBig = False
        self.beginCheckManualOkFlagBig = False
        self.cutterQueue = queue.Queue()  # 将队列清空
        self.reload_cutter_cam_check_thres_big()
        return "ok"

    def web_request_reset_small_cutter_self(self):
        """
        界面上点击了小铡刀单独复位按钮
        :return:
        """
        ret = self.smallCutterZmc.cutter_zmc_reset_itself()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.camZmcIndex)
            return ret
        self.smallCutterZmc.close_buzzer_alarm()
        self.handCutBoardFlagSmall = False
        self.handCutExReset = True
        self.finalCheckFlagSmall = False
        self.finalCheckModifySmall = False
        self.beginCheckAdjustFlagSmall = False
        self.beginCheckModifySmall = False
        self.manualBeginCheckAngleOkSmall = False
        self.reload_cutter_cam_check_thres_small()
        # 将小铡刀的队列的数据清空
        # 复位的时候,先检测下这个信号是否存在,如果存在了,就取出一条数据,然后清除
        ret, val = self.smallCutterZmc.get_allow_take_board_state()
        if val == 1:
            self.smallCutterZmc.set_allow_take_board_clear()  # 清空信号
            self.logger.debug("id_{} 小铡刀: 复位的时候检测到抓板信号(modbus_bit(65) = 1),从大铡刀那里获取数据".format(self.bigCutterZmcIndex))
            if self.cutterQueue.empty():
                self.logger.debug("id_{} 小铡刀: 大铡刀数据队列为空,小铡刀数据获取失败".format(self.bigCutterZmcIndex))
                self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                return
            else:
                self.cutterQueueSmall = queue.Queue()
                data = self.cutterQueue.get()  # 将大铡刀的数据获取到
                self.cutterQueueSmall.put(data)
        self.cutterQueueSmall = queue.Queue()
        return "ok"

    def web_request_close_reset_modal(self):
        """
        关闭复位提示框
        :return:
        """
        self.resetCheck = False
        return "ok"

    def web_request_reset_all(self):
        """
        前端界面点击了总复位按钮.
        :return:
        """
        self.logger.debug("id_{} 点击了总复位按钮,开始复位".format(self.camZmcIndex))
        ret = self.bigCutterZmc.cutter_zmc_reset()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
        msgVal = {
            "val": "resetAllModal",
            "modalVisible": True,
            "resetInfo": "设备复位中..."
        }
        send_produce_state_to_ui(msgVal)
        time.sleep(0.5)
        self.resetCheck = True
        while self.resetCheck:
            ret1, val1 = self.camZmc.is_reset_state()
            ret2, val2 = self.cbjZmc.is_reset_state()
            ret3, val3 = self.bigCutterZmc.is_reset_state()
            ret4, val4 = self.smallCutterZmc.is_reset_state()
            info1 = "1. 上料复位中..." if val1 == 1 else "1. 上料复位完成!"
            info2 = "2. 裁切机复位中..." if val2 == 1 else "2. 裁切复位完成!"
            info3 = "1. 大铡刀复位中..." if val3 == 1 else "3. 大铡刀复位完成!"
            info4 = "1. 小铡刀复位中..." if val4 == 1 else "3. 小铡刀复位完成!"
            if val1 == 0 and val2 == 0 and val3 == 0 and val4 == 0:  # 全部是复位完成状态,就退出
                self.resetCheck = False
                msgVal = {
                    "val": "resetAllModal",
                    "modalVisible": False,
                    "resetInfo": "设备复位完成..."
                }
                send_produce_state_to_ui(msgVal)
            else:
                msgVal = {
                    "val": "resetAllModal",
                    "modalVisible": True,
                    "resetInfo": info1 + " " + info2 + " " + info3 + " " + info4
                }
                send_produce_state_to_ui(msgVal)
            gevent.sleep(0.5)
        msgVal = {
            "val": "resetAllModal",
            "modalVisible": False,
            "resetInfo": "设备复位完成..."
        }
        self.cutterQueue = queue.Queue()
        self.cutterQueueSmall = queue.Queue()
        send_produce_state_to_ui(msgVal)

        return "ok"

    def web_request_close_produce_start_modal(self):
        """
        前端界面点击,关闭设备启动提示框.
        :return:
        """
        self.produceStartCheck = False
        return "ok"

    def web_request_disable_calc_image(self, getImageIsAllowed):
        """
        上料的拍照功能是否开启
        :param getImageIsAllowed,是否暂停拍照功能
        :return:
        """
        self.isAllowGetImage = getImageIsAllowed
        return "ok"

    def web_request_re_calc_first_board(self):
        """
        界面上点击了重新做首板的逻辑
        :return:
        """
        self.isFirstBoard = True
        return "ok"

    def web_request_change_order(self, orderInfo):
        """
        界面上点击了更换工单
        :param orderInfo:工单的信息
        :return:
        """
        if orderInfo["key"] == self.key:
            return "更换工单失败,要更换的工单和正在作业的工单相同,请去人已选择的工单是否是要更换的工单."
        self.order_info_init(orderInfo)
        if self.linesQueue is not None:
            self.linesQueue = queue.Queue()  # 更换工单以后将切线队列置位空
        if orderInfo.get("lengthUnit", "mm") == "mm":
            orderWidthMm = orderInfo["width"]
            orderHeightMm = orderInfo["height"]
        else:
            orderWidthMm = orderInfo["width"]
            orderHeightMm = orderInfo["height"]
        self.logger.debug("id_{} 界面上点击了更换工单按钮,新的工单信息: key:{} 物料号:{},录入的宽高:({},{}),识别使用的宽高:({},{}),是否易断板:{}".format(
            self.camZmcIndex, self.key, self.prodId, orderWidthMm, orderHeightMm, self.widthMm, self.heightMm, self.boardBreak))
        return "ok"

    def web_request_start_produce(self, orderInfo):
        """
        前端界面点击了自动作业开启的按钮.
        :param orderInfo:开启自动作业的工单信息
        :return:
        """

        # 1.自动作业状态初始化
        self.produce_prepare_init()
        self.order_info_init(orderInfo)
        # 去测试下工单的功能
        # self.test_order_edge_problem()
        produceInitInfo = "id_{} 自动作业参数初始化完成,参数值如下:\n".format(self.camZmcIndex)
        produceInitInfo += "id_{} 工单参数: 物料号: {}, width: {},height: {},第一刀留宽: {},第二刀留宽: {},第三刀留宽: {},第四刀留宽: {},易断板: {}\n".format(
            self.camZmcIndex, self.prodId, self.widthMm, self.heightMm, self.topMm, self.leftMm, self.bottomMm, self.rightMm, self.boardBreak)
        produceInitInfo += "id_{} 识别阈值: 偏大: {},偏小: {},内板位置: {},物料高度Max: {},物料高度Min: {},首板对比1: {},首板对比2: {},首板对比总: {}\n".format(
            self.camZmcIndex, self.calcThresBig, self.calcThresSmall, self.innerToEdgeThres, self.totalHeightMax, self.totalHeightMin,
            self.firstBoardErrorThres, self.secondBoardErrorThres, self.totalBoardErrorThres)
        produceInitInfo += "id_{} 大铡刀阈值: 首检角度: {},移动补偿: {},角度补偿: {},终检第一块: {},终检第二块: {},终检前角: {},终检后角: {}\n".format(
            self.camZmcIndex, self.beginAngleThresBig, self.cutterMoveOffsetBig, self.beginAngleOffsetBig, self.finalFirstBoardThresBig,
            self.finalSecondBoardThresBig,
            self.finalFrontAngleBig, self.finalBackAngleBig)
        produceInitInfo += "id_{} 小铡刀阈值: 首检角度: {},移动补偿: {},角度补偿: {},终检第一块: {},终检第二块: {},终检前角: {},终检后角: {}\n".format(
            self.camZmcIndex, self.beginAngleThresSmall, self.cutterMoveOffsetSmall, self.beginAngleOffsetSmall, self.finalFirstBoardThresSmall,
            self.finalSecondBoardThresSmall,
            self.finalFrontAngleSmall, self.finalBackAngleSmall)
        produceInitInfo += "id_{} 切割参数: 下刀深度: {},切割速度: 第一刀: {},剩余刀: {},裁切机极限X: {},裁切机极限Y: {}".format(
            self.camZmcIndex, self.cutDeep, self.firstCutSpeed, self.cutSpeed, self.cbjLimitX, self.cbjLimitY)
        print(produceInitInfo)
        self.logger.debug(produceInitInfo)
        # 2.启动设备
        ret = self.bigCutterZmc.cutter_zmc_start()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
            return ret
        # 3.设置是单拼还是双拼
        if self.jointNumber == "4":
            ret = self.bigCutterZmc.set_4pin_flag()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
                return ret
        else:
            ret = self.bigCutterZmc.set_6pin_flag()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.camZmcIndex)
                return ret

        # 4.启动提示框打开
        msgVal = {
            "val": "produceStartModal",
            "modalVisible": True,
            "produceStartInfo": "设备启动中..."
        }
        send_produce_state_to_ui(msgVal)
        gevent.sleep(0.5)
        self.produceStartCheck = True
        self.produceStartOk = False
        info1 = info2 = info3 = info4 = ""
        if ec.eapOnline:
            ec.realStatusData.statusId = DeviceStatus.Initial.name  # 将设备置位初始化状态
        while self.produceStartCheck:
            _, val1 = self.camZmc.is_running()
            _, val2 = self.cbjZmc.is_running()
            _, val3 = self.bigCutterZmc.is_running()
            _, val4 = self.smallCutterZmc.is_running()
            info1 = "1. 上料启动中..." if val1 == 0 else "1. 上料启动成功!"
            info2 = "2. 裁切机启动中..." if val2 == 0 else "2. 裁切机启动成功!"
            info3 = "3. 大铡刀启动中..." if val3 == 0 else "3. 大铡刀启动成功!"
            info4 = "4. 小铡刀启动中..." if val4 == 0 else "4. 小铡刀启动成功!"
            if val1 == 1 and val2 == 1 and val3 == 1:
                self.produceStartCheck = False
                self.produceStartOk = True
                msgVal = {
                    "val": "produceStartModal",
                    "modalVisible": False,
                    "produceStartInfo": ""
                }
            else:
                self.produceStartOk = False
                msgVal = {
                    "val": "produceStartModal",
                    "modalVisible": True,
                    "produceStartInfo": info1 + " " + info2 + " " + info3 + " " + info4
                }
            send_produce_state_to_ui(msgVal)
            gevent.sleep(0.1)
        if self.produceStartOk:
            msgVal = {
                "val": "produceStartModal",
                "modalVisible": False,
                "produceStartInfo": ""
            }
            send_produce_state_to_ui(msgVal)
            # 启动成功以后,将设备置位空闲状态
            if ec.eapOnline:
                ec.realStatusData.statusId = DeviceStatus.Idle.name  # 将设备置位空闲状态
        else:
            return "启动失败!" + info1 + " " + info2 + " " + info3 + " " + info4

        # 自动作业启动成功以后,开启后台的线程.
        self.deviceStates.workStopFlag = False
        self.produceListenerThread = threading.Thread(target=self.produce_listener,
                                                      daemon=True, name="produceListenerThread")
        self.produceListenerThread.start()
        return "ok"

    def produce_listener(self):
        """
        自动作业监听线程函数,主要用来监控自动作业过程中的各个作业函数的任务.
        :return:
        """
        self.logger.debug("自动作业监听线程开启!")
        self.camZmcTaskThead = threading.Thread(target=self.cam_zmc_task,
                                                daemon=True, name="camZmcTaskThead")
        self.cbjZmcTaskThead = threading.Thread(target=self.cbj_zmc_task,
                                                daemon=True, name="cbjZmcTaskThead")
        self.bigCutterZmcTaskThread = threading.Thread(target=self.big_cutter_zmc_task,
                                                       daemon=True, name="bigCutterZmcTaskThread")
        self.smallCutterZmcTaskThread = threading.Thread(target=self.small_cutter_zmc_task,
                                                         daemon=True, name="smallCutterZmcTaskThread")
        self.checkTakeBoardTaskThread = threading.Thread(target=self.check_take_board_task,
                                                         daemon=True, name="checkTakeBoardTask")
        self.checkTakeBoardTaskThread.start()
        self.camZmcTaskThead.start()
        self.cbjZmcTaskThead.start()
        self.bigCutterZmcTaskThread.start()
        self.smallCutterZmcTaskThread.start()

        while not self.deviceStates.workStopFlag:
            gevent.sleep(0.5)
        # 防止线程掉线
        camZmcTaskThread = self.camZmcTaskThead
        cbjZmcTaskThread = self.cbjZmcTaskThead
        bigCutterZmcTaskThread = self.bigCutterZmcTaskThread
        smallCutterZmcTaskThread = self.smallCutterZmcTaskThread
        checkTakeBoardThread = self.checkTakeBoardTaskThread

        gevent.sleep(1)
        if camZmcTaskThread.is_alive():
            common_tools.stop_thread(camZmcTaskThread)
        if cbjZmcTaskThread.is_alive():
            common_tools.stop_thread(cbjZmcTaskThread)
        if bigCutterZmcTaskThread.is_alive():
            common_tools.stop_thread(bigCutterZmcTaskThread)
        if smallCutterZmcTaskThread.is_alive():
            common_tools.stop_thread(smallCutterZmcTaskThread)
        if checkTakeBoardThread.is_alive():
            common_tools.stop_thread(checkTakeBoardThread)
        self.logger.debug(f"id_{self.camZmcIndex} 检测到自动作业退出标志,强制结束各个作业线程,"
                          f"上料:{self.camZmcIndex},裁切:{self.cbjZmcIndex},铡刀:{self.bigCutterZmcIndex}")

    def big_cutter_zmc_task(self):
        """
        前铡刀作业函数
        :return:
        """
        self.logger.debug("大铡刀作业任务函数开启")
        self.finalCheckFlagBig = False
        self.beginCheckAdjustFlagBig = False
        self.finalCheckModifyBig = False
        self.beginCheckManualOkFlagBig = False
        self.finalCheckAgainBig = False  # 大铡刀终点检测重新检测标志
        self.handCutBoardFlagBig = False  # 大铡刀终点检测是否人工确认铡板
        while True:
            if self.deviceStates.workStopFlag:
                self.logger.debug("workStopFlag = True,大铡刀作业任务函数退出.")
                return
            ret, val = self.bigCutterZmc.get_allow_take_pic_begin_check()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                return
            if val == 1:
                # 每次收到检测的时候,都打开门报警
                newData = {
                    "cutterZmcIndex": self.bigCutterZmcIndex
                }
                self.update_working_info_to_db_and_web(newData)
                self.bigCutterZmc.set_allow_take_pic_begin_check_clear()
                self.logger.debug("id_{} 大铡刀起点检测: 收到拍照信号,1号相机开始拍照".format(self.bigCutterZmcIndex))
                self.bigCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
                self.cutterImageBig1 = None
                res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                if res != "ok":
                    self.logger.debug("id_{} 大铡刀起点检测: 1号相机拍照失败,重新打开相机开始拍照".format(self.bigCutterZmcIndex))
                    res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                    if res != "ok":
                        self.keep_zmc_read_write_error(self.cutterImageBig1, "cameraError", self.bigCutterZmcIndex)
                        return
                endwith = "adjust" if self.beginCheckAdjustFlagBig else "first"
                light1First, light2First, imageRes = get_first_thres_point_begain_check(self.cutterImageBig1, self.bigCutterCamCal.light1Pos,
                                                                                        self.bigCutterCamCal.light2Pos)
                save_big_begin_check_image(self.bigCutterZmcIndex, self.cutterImageBig1, endwith=endwith)
                save_big_begin_check_res_image(self.bigCutterZmcIndex, imageRes, endwith=endwith)
                if (light1First is None or light2First is None) and not self.beginCheckManualOkFlagBig:
                    cutterHintInfo = "大铡刀有灯管全黑,这个时候考虑是冲板,铡刀后移50个mm,再检测一次."
                    self.logger.debug("id_{} 起点检测: {}".format(self.bigCutterZmcIndex, cutterHintInfo))
                    self.bigCutterZmc.move_x(-50)
                    gevent.sleep(1)
                    res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                    light1First, light2First, imageRes = get_first_thres_point_begain_check(self.cutterImageBig1,
                                                                                            self.bigCutterCamCal.light1Pos,
                                                                                            self.bigCutterCamCal.light2Pos)
                    save_big_begin_check_image(self.bigCutterZmcIndex, self.cutterImageBig1, endwith=endwith)
                    save_big_begin_check_res_image(self.bigCutterZmcIndex, imageRes, endwith=endwith)
                    if light1First is None or light2First is None:
                        cutterHintInfo = "大铡刀后退了50个mm依旧检测到有黑色的灯管,弹框提示工人操作"
                        self.logger.debug("id_{} 起点检测: {}".format(self.bigCutterZmcIndex, cutterHintInfo))
                        self.beginCheckModifyBig = True
                        self.send_front_cutter_begin_check_modal_to_web(imageRes, cutterHintInfo)
                        while self.beginCheckModifyBig:
                            gevent.sleep(0.3)
                            continue
                        gevent.sleep(0.5)
                        continue

                light1Offset, light2Offset, angleCheck = self.bigCutterCamCal.get_offset_to_cutter_by_ruler(1, light1First, light2First)
                angleAdjust = round(angleCheck + self.cutterTopMiddleAngle, 2)
                self.logger.debug("id_{} 大铡刀起点检测: 1号灯管 = {},2号灯管 = {},角度: check = {},topM = {},角度补偿 = {},sum = {}".format(
                    self.bigCutterZmcIndex, light1Offset, light2Offset, angleCheck, self.cutterTopMiddleAngle, self.beginAngleOffsetBig, angleAdjust))
                # 加上角度补偿值:
                angleAdjustReal = angleAdjust + self.beginAngleOffsetBig
                if (abs(angleAdjustReal) > self.beginAngleThresBig) and (not self.beginCheckManualOkFlagBig):
                    if not self.beginCheckAdjustFlagBig:
                        ret = self.bigCutterZmc.set_begin_check_angle_offset(angleAdjustReal)
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                            return
                        ret = self.bigCutterZmc.set_begin_check_angle_fail()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                            return
                        self.logger.debug("id_{} 大铡刀起点检测: 验证失败,进行角度调整,调整角度 = {}".format(self.bigCutterZmcIndex, angleAdjust))
                        self.beginAngleThresBig += 0.1
                        self.beginCheckAdjustFlagBig = True
                        gevent.sleep(0.05)
                        continue
                    else:
                        # 如果这里调整完之后,检测依旧没有通过,人工弹窗提示工人进行操作.正值逆时针调整,负值顺时针调整
                        if angleAdjustReal > 0:
                            cutterHintInfo = "id_{} 大铡刀起点检测: 角度调整完之后,依旧有角度,请人工逆时针调整,角度 = {:.2f}".format(self.bigCutterZmcIndex, angleAdjustReal)
                        else:
                            cutterHintInfo = "id_{} 大铡刀起点检测: 角度调整完之后,依旧有角度,请人工调整顺时针调整,角度 = {:.2f}".format(self.bigCutterZmcIndex, angleAdjustReal)
                        self.logger.debug(cutterHintInfo)
                        self.beginCheckModifyBig = True
                        self.send_front_cutter_begin_check_modal_to_web(imageRes, cutterHintInfo)
                        while self.beginCheckModifyBig and not self.deviceStates.workStopFlag:
                            gevent.sleep(0.2)
                            continue
                        gevent.sleep(0.5)
                        continue
                else:
                    isManual = "人工确认" if self.beginCheckManualOkFlagBig else "非人工确认"
                    if self.beginCheckManualOkFlagBig:
                        self.beginCheckManualOkFlagBig = False
                    beginCheckToCutter = round((light1Offset + light2Offset) / 2, 2)
                    cutterMoveDis = round(beginCheckToCutter + self.secondBoardLenBig + self.cutterMoveOffsetBig, 2)
                    ret = self.bigCutterZmc.set_begin_check_move_distance(cutterMoveDis)
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                        return
                    ret = self.bigCutterZmc.set_begin_check_angle_ok()
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                        return
                    self.logger.debug("id_{} 大铡刀起点检测: {}, 验证成功,角度 = {:.2f},角度补偿 = {:.2f},板边到铡刀距离:{},第一块板长:{},移动距离:{},移动补偿:{}".format(
                        self.bigCutterZmcIndex, isManual, angleAdjust, self.beginAngleOffsetBig, beginCheckToCutter, self.secondBoardLenBig, cutterMoveDis,
                        self.cutterMoveOffsetBig))
                    self.beginCheckAdjustFlagBig = False
                    self.finalCheckFlagBig = True
                    self.reload_cutter_cam_check_thres_big()

                secondAdjust = False  # 是否进行了二次调整的标志.
                # 验证之前如果是六拼板,搞一个标志位是第几块
                self.finalCheckTimes = 1  # 表示是第一次终点检测
                while self.finalCheckFlagBig:
                    if self.jointNumber == "4":
                        if self.deviceStates.workStopFlag:
                            self.logger.debug("id_{} workStopFlag = True,大铡刀铡刀作业任务函数退出.".format(self.camZmcIndex))
                            return
                        ret, val = self.bigCutterZmc.get_allow_take_pic_final_check()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                            return
                        if val == 1:
                            self.bigCutterZmc.set_allow_take_pic_final_check_clear()
                            self.logger.debug("id_{} 大铡刀终点检测: 收到拍照信号,开始拍照".format(self.bigCutterZmcIndex))
                            res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                            if res != "ok":
                                self.logger.debug("id_{} 大铡刀终点检测: 1号相机拍照失败,重新打开相机开始拍照".format(self.bigCutterZmcIndex))
                                res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                                if res != "ok":
                                    self.keep_zmc_read_write_error(self.cutterImageBig1, "cameraError", self.bigCutterZmcIndex)
                                    return
                            res, self.cutterImageBig2 = self.bigCutterCamCal.get_cutter_image(2)
                            if res != "ok":
                                self.logger.debug("id_{} 大铡刀终点检测: 2号相机拍照失败,重新打开相机开始拍照".format(self.bigCutterZmcIndex))
                                res, self.cutterImageBig2 = self.bigCutterCamCal.get_cutter_image(2)
                                if res != "ok":
                                    self.keep_zmc_read_write_error(self.cutterImageBig2, "cameraError", self.bigCutterZmcIndex)
                                    return
                            finalLight1First, finalLight2First, imgRes1 = get_first_thres_point_final_check_cam_1(self.cutterImageBig1,
                                                                                                                  self.bigCutterCamCal.light1Pos,
                                                                                                                  self.bigCutterCamCal.light2Pos)
                            finalLight3First, finalLight4First, imgRes2 = get_first_thres_point_final_check_cam_2(self.cutterImageBig2,
                                                                                                                  self.bigCutterCamCal.light3Pos,
                                                                                                                  self.bigCutterCamCal.light4Pos)
                            # 保存图片
                            save_front_final_check_image(self.bigCutterZmcIndex, self.cutterImageBig1, self.cutterImageBig2)
                            save_front_final_check_image_res(self.bigCutterZmcIndex, imgRes1, imgRes2)

                            if (finalLight1First is None or finalLight2First is None or finalLight3First is None or finalLight4First is None) \
                                    and not self.handCutBoardFlagBig:
                                if finalLight1First is None or finalLight2First is None:
                                    self.frontImageSend = imgRes1
                                else:
                                    self.frontImageSend = imgRes2
                                cutterHintInfo = "id_{} 大铡刀终点检测: 检测到某个灯管全黑,请人工确认!"
                                self.logger.debug(cutterHintInfo)
                                self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, cutterHintInfo)
                                self.finalCheckModifyBig = True
                                while self.finalCheckModifyBig:
                                    gevent.sleep(0.5)
                                    continue
                                if ec.eapOnline:
                                    request_alarm_report(AlarmType.R, 12)
                                gevent.sleep(0.5)
                                continue

                            # 如果找到了灯管的遮挡位置,就开始计算距离和角度
                            light1Offset, light2Offset, backAngle = self.bigCutterCamCal.get_offset_to_cutter_by_ruler(1, finalLight1First,
                                                                                                                       finalLight2First)
                            light3Offset, light4Offset, frontAngle = self.bigCutterCamCal.get_offset_to_cutter_by_ruler(2, finalLight3First,
                                                                                                                        finalLight4First)
                            firstBoardCheck = round((light3Offset + light4Offset) / 2, 2)
                            frontAngleCheck = round(frontAngle + self.cutterTopMiddleAngle, 2)
                            secondBoardCheck = round((light1Offset + light2Offset) / 2, 2)
                            backAngleCheck = round(abs(backAngle) - abs(self.cutterBottomMiddleAngle), 2)
                            firstBoardError = round(firstBoardCheck - self.firstBoardLenBig, 2)
                            secondBoardError = round(secondBoardCheck - self.secondBoardLenBig, 2)
                            totalBoardError = round(firstBoardCheck + secondBoardCheck - self.firstBoardLenBig - self.secondBoardLenBig, 2)
                            self.logger.debug("id_{} 大铡刀终点检测: 2号相机:3号灯管={:.2f},4号灯管={:.2f},第一块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                                self.bigCutterZmcIndex, light3Offset, light4Offset, firstBoardCheck, frontAngleCheck, firstBoardError))
                            self.logger.debug("id_{} 大铡刀终点检测: 1号相机:1号灯管={:.2f},2号灯管={:.2f},第二块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                                self.bigCutterZmcIndex, light1Offset, light2Offset, secondBoardCheck, backAngleCheck, secondBoardError))
                            if not self.boardBreak:
                                # 如果不是易断板
                                if ((abs(frontAngleCheck) > self.finalFrontAngleBig) or (abs(firstBoardError) > self.finalFirstBoardThresBig)
                                    or (abs(backAngleCheck) > self.finalBackAngleBig) or (abs(secondBoardError) > self.finalSecondBoardThresBig)
                                ) and not self.handCutBoardFlagBig:  # 每块板都进行二次调整,调整到一个固定的值
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整后,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                    else:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整前,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                    self.logger.debug(debugInfo)
                                    if abs(frontAngleCheck) > self.finalFrontAngleBig or abs(backAngleCheck) > self.finalBackAngleBig:
                                        # 终点检测,非第一块板长引起的,要给这个个信息发送给前端
                                        self.logger.debug("id_{} 终点检测: 验证出错,弹窗提示工人操作.".format(self.bigCutterZmcIndex))
                                        if abs(frontAngleCheck) > self.finalFrontAngleBig:
                                            self.frontImageSend = imgRes2
                                        else:
                                            self.frontImageSend = imgRes1
                                        self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                        self.finalCheckModifyBig = True
                                        while self.finalCheckModifyBig:
                                            gevent.sleep(0.5)
                                            continue
                                        if ec.eapOnline:
                                            request_alarm_report(AlarmType.R, 12)
                                        if self.handCutBoardFlagBig:
                                            continue
                                        gevent.sleep(0.5)
                                        continue
                                    else:
                                        if not secondAdjust:
                                            cutterFinalAdjust = -firstBoardError  # 加上二次调整的补偿值.
                                            self.logger.debug("id_{} 大铡刀终点检测: 进行二次调整,调整的值 = {:.2f},第一块误差 = {:.2f}".format(self.bigCutterZmcIndex,
                                                                                                                                                cutterFinalAdjust,
                                                                                                                                                firstBoardError))
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_flag()
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            secondAdjust = True
                                            continue
                                        else:
                                            debugInfo = "id_{} 大铡刀终点检测: 二次调整后仍然没有通过.第一块偏差:{},阈值:{}".format(
                                                self.bigCutterZmcIndex, firstBoardError, self.firstBoardErrorThres)
                                            self.logger.debug(debugInfo)
                                            self.frontImageSend = imgRes2
                                            self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                            self.finalCheckModifyBig = True
                                            while self.finalCheckModifyBig:
                                                gevent.sleep(0.5)
                                                continue
                                            if ec.eapOnline:
                                                request_alarm_report(AlarmType.R, 12)
                                            if self.handCutBoardFlagBig:
                                                continue
                                            gevent.sleep(0.5)
                                            continue
                                # 如果验证通过
                                else:
                                    manualInfo = "人工确认" if self.handCutBoardFlagBig else "非人工确认"
                                    if self.handCutBoardFlagBig:
                                        self.handCutBoardFlagBig = False
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整后,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                    else:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整前,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                    self.logger.debug(debugInfo)
                                    ret = self.bigCutterZmc.set_final_check_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    self.logger.debug(
                                        "id_{} 大铡刀终点检测后下发小铡刀抓板数据： 板长： {}， 角度：{}".format(self.bigCutterZmcIndex, firstBoardCheck,
                                                                                                             self.twoCutterAngleOffset))
                                    ret = self.smallCutterZmc.set_board_len_small_offset(firstBoardCheck)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    ret = self.smallCutterZmc.set_angle_len_small_offset(self.twoCutterAngleOffset)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    else:
                                        # 存放后铡刀的数据信息,放入到队列当中
                                        b = {
                                            "cutterIndexSmall": str(self.bigCutterZmcIndex) + '_01',
                                            "firstBoardLenSmall": self.firstBoardLenSmall,
                                            "secondBoardLenSmall": self.secondBoardLenSmall,
                                            "leftMidAngleSmall": self.leftMiddleAngleUp,
                                            "rightMidAngleSmall": self.rightMiddleAngleUp,
                                            "twoCutterOffset": self.cutterAngleOffsetUp
                                        }
                                        self.cutterQueue.put(b)
                                        c = {
                                            "cutterIndexSmall": str(self.bigCutterZmcIndex) + '_02',
                                            "firstBoardLenSmall": self.thirdBoardLenSmall,
                                            "secondBoardLenSmall": self.forthBoardLenSmall,
                                            "leftMidAngleSmall": self.leftMiddleAngleDown,
                                            "rightMidAngleSmall": self.rightMiddleAngleDown,
                                            "twoCutterOffset": self.cutterAngleOffsetDown
                                        }
                                        self.cutterQueue.put(c)
                                        # 补偿角度重新计算,考虑到后铡刀的角度.这个时候后铡刀的角度也要考虑进去.
                                        self.cutterAngleOffsetUp = self.cutterAngleOffsetUp
                                        ret = self.smallCutterZmc.set_angle_offset(self.cutterAngleOffsetUp)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error('set small_cutter 124 failed.后铡刀控制器通信异常,请检查电源线和网线!', "small_cutter",
                                                                           self.bigCutterZmcIndex)
                                            return
                                        self.logger.debug(
                                            "id_{},cut_id:{} 大铡刀完成铡板,底层角度补偿写入成功,补偿角度={:.2f},此时的cutter_q(size={})".format(
                                                self.bigCutterZmcIndex, self.prodId, self.cutterAngleOffsetUp,
                                                self.cutterQueue.qsize()))
                                        self.finalCheckFlagBig = False
                                        self.finalCheckModifyBig = False

                            # 如果是易断板
                            else:
                                if ((abs(frontAngleCheck) > self.finalFrontAngleBig) or
                                    abs(firstBoardError) > self.finalFirstBoardThresBig or
                                    secondBoardError < -(self.finalSecondBoardThresBig - 3) or
                                    (not secondAdjust)) and not self.handCutBoardFlagBig:
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整后,验证失败,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                    else:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整前,验证失败,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                    self.logger.debug(debugInfo)
                                    if abs(frontAngleCheck) > self.finalFrontAngleBig:
                                        cutterHintInfo = "id_{} 大铡刀终点检测: 易断板,前角超过阈值.检测值: {},阈值: {}".format(self.bigCutterZmcIndex, frontAngleCheck,
                                                                                                                                self.finalFrontAngleBig)
                                        self.logger.debug(cutterHintInfo)
                                        self.frontImageSend = imgRes2
                                        self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, cutterHintInfo)
                                        self.finalCheckModifyBig = True
                                        while self.finalCheckModifyBig:
                                            gevent.sleep(0.3)
                                            continue
                                        if ec.eapOnline:
                                            request_alarm_report(AlarmType.R, 12)
                                        gevent.sleep(0.3)
                                        continue
                                    elif (secondBoardError + firstBoardError) < -self.finalFoldThresBig:
                                        cutterHintInfo = "id_{} 大铡刀终点检测: 易断板,检测到叠板.检测值: {},阈值: {}".format(self.bigCutterZmcIndex,
                                                                                                                              secondBoardError, self.finalFoldThresBig)
                                        self.logger.debug(cutterHintInfo)
                                        self.frontImageSend = imgRes1
                                        self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, cutterHintInfo)
                                        self.finalCheckModifyBig = True
                                        while self.finalCheckModifyBig:
                                            gevent.sleep(0.3)
                                            continue
                                        gevent.sleep(0.3)
                                        continue
                                    else:
                                        if not secondAdjust:
                                            cutterFinalAdjust = -firstBoardError
                                            self.logger.debug("id_{} 大铡刀终点检测: 易断板,进行二次调整,调整的值 = {:.2f},第一块板误差 = {:.2f}".format(self.bigCutterZmcIndex,
                                                                                                                                                         cutterFinalAdjust,
                                                                                                                                                         -firstBoardError))
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_flag()
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            secondAdjust = True
                                            continue
                                        else:
                                            debugInfo = "id_{} 大铡刀终点检测: 易断板,二次调整后仍然没有通过.第一块偏差:{},阈值:{}".format(
                                                self.bigCutterZmcIndex, firstBoardError, self.firstBoardErrorThres)
                                            self.logger.debug(debugInfo)
                                            self.frontImageSend = imgRes2
                                            self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                            self.finalCheckModifyBig = True
                                            while self.finalCheckModifyBig:
                                                gevent.sleep(0.5)
                                                continue
                                            if self.handCutBoardFlagBig:
                                                continue
                                            gevent.sleep(0.5)
                                            continue

                                else:
                                    manualInfo = "人工确认" if self.handCutBoardFlagBig else "非人工确认"
                                    if self.handCutBoardFlagBig:
                                        self.handCutBoardFlagBig = False
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整后,易断板,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{}, {} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                    else:
                                        debugInfo = "id_{} 大铡刀终点检测: 二次调整前,验证通过,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{}, {} ".format(
                                            self.bigCutterZmcIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                    self.logger.debug(debugInfo)
                                    ret = self.bigCutterZmc.set_final_check_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    ret = self.smallCutterZmc.set_board_len_small_offset(firstBoardCheck)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    else:
                                        # 存放后铡刀的数据信息,放入到队列当中
                                        b = {
                                            "cutterIndexSmall": str(self.bigCutterZmcIndex) + '_01',
                                            "firstBoardLenSmall": self.firstBoardLenSmall,
                                            "secondBoardLenSmall": self.secondBoardLenSmall,
                                            "leftMidAngleSmall": self.leftMiddleAngleUp,
                                            "rightMidAngleSmall": self.rightMiddleAngleUp,
                                            "twoCutterOffset": self.cutterAngleOffsetUp
                                        }
                                        self.cutterQueue.put(b)
                                        c = {
                                            "cutterIndexSmall": str(self.bigCutterZmcIndex) + '_02',
                                            "firstBoardLenSmall": self.thirdBoardLenSmall,
                                            "secondBoardLenSmall": self.forthBoardLenSmall,
                                            "leftMidAngleSmall": self.leftMiddleAngleDown,
                                            "rightMidAngleSmall": self.rightMiddleAngleDown,
                                            "twoCutterOffset": self.cutterAngleOffsetDown
                                        }
                                        self.cutterQueue.put(c)
                                        # 补偿角度重新计算,考虑到后铡刀的角度.这个时候后铡刀的角度也要考虑进去.
                                        self.cutterAngleOffsetUp = self.cutterAngleOffsetUp
                                        ret = self.smallCutterZmc.set_angle_offset(self.cutterAngleOffsetUp)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(
                                                'set small_cutter 124 failed.后铡刀控制器通信异常,请检查电源线和网线!', "small_cutter",
                                                self.bigCutterZmcIndex)
                                            return
                                        self.logger.debug(
                                            "id_{},cut_id:{} 大铡刀完成铡板,底层角度补偿写入成功,补偿角度={:.2f},此时的cutter_q(size={})".format(
                                                self.bigCutterZmcIndex, self.prodId, self.cutterAngleOffsetUp,
                                                self.cutterQueue.qsize()))
                                        self.finalCheckFlagBig = False
                                        self.finalCheckModifyBig = False

                        else:
                            gevent.sleep(0.3)
                            continue
                    elif self.jointNumber == "6":
                        if self.deviceStates.workStopFlag:
                            self.logger.debug("id_{} workStopFlag = True,大铡刀铡刀作业任务函数退出.".format(self.camZmcIndex))
                            return
                        ret, val = self.bigCutterZmc.get_allow_take_pic_final_check()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                            return
                        if val == 1:
                            self.bigCutterZmc.set_allow_take_pic_final_check_clear()
                            self.logger.debug("id_{} 大铡刀终点检测: 收到拍照信号,开始拍照".format(self.bigCutterZmcIndex))
                            res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                            if res != "ok":
                                self.logger.debug("id_{} 大铡刀终点检测: 1号相机拍照失败,重新打开相机开始拍照".format(self.bigCutterZmcIndex))
                                res, self.cutterImageBig1 = self.bigCutterCamCal.get_cutter_image(1)
                                if res != "ok":
                                    self.keep_zmc_read_write_error(self.cutterImageBig1, "cameraError", self.bigCutterZmcIndex)
                                    return
                            res, self.cutterImageBig2 = self.bigCutterCamCal.get_cutter_image(2)
                            if res != "ok":
                                self.logger.debug("id_{} 大铡刀终点检测: 2号相机拍照失败,重新打开相机开始拍照".format(self.bigCutterZmcIndex))
                                res, self.cutterImageBig2 = self.bigCutterCamCal.get_cutter_image(2)
                                if res != "ok":
                                    self.keep_zmc_read_write_error(self.cutterImageBig2, "cameraError", self.bigCutterZmcIndex)
                                    return
                            finalLight1First, finalLight2First, imgRes1 = get_first_thres_point_final_check_cam_1(self.cutterImageBig1,
                                                                                                                  self.bigCutterCamCal.light1Pos,
                                                                                                                  self.bigCutterCamCal.light2Pos)
                            finalLight3First, finalLight4First, imgRes2 = get_first_thres_point_final_check_cam_2(self.cutterImageBig2,
                                                                                                                  self.bigCutterCamCal.light3Pos,
                                                                                                                  self.bigCutterCamCal.light4Pos)
                            # 保存图片
                            save_front_final_check_image(self.bigCutterZmcIndex, self.cutterImageBig1, self.cutterImageBig2)
                            save_front_final_check_image_res(self.bigCutterZmcIndex, imgRes1, imgRes2)

                            if (finalLight1First is None or finalLight2First is None or finalLight3First is None or finalLight4First is None) \
                                    and not self.handCutBoardFlagBig:
                                if finalLight1First is None or finalLight2First is None:
                                    self.frontImageSend = imgRes1
                                else:
                                    self.frontImageSend = imgRes2
                                cutterHintInfo = "id_{} 大铡刀终点检测: 检测到某个灯管全黑,请人工确认!"
                                self.logger.debug(cutterHintInfo)
                                self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, cutterHintInfo)
                                self.finalCheckModifyBig = True
                                while self.finalCheckModifyBig:
                                    gevent.sleep(0.5)
                                    continue
                                gevent.sleep(0.5)
                                continue

                            # 如果找到了灯管的遮挡位置,就开始计算距离和角度
                            light1Offset, light2Offset, backAngle = self.bigCutterCamCal.get_offset_to_cutter_by_ruler(1, finalLight1First,
                                                                                                                       finalLight2First)
                            light3Offset, light4Offset, frontAngle = self.bigCutterCamCal.get_offset_to_cutter_by_ruler(2, finalLight3First,
                                                                                                                        finalLight4First)
                            firstBoardCheck = round((light3Offset + light4Offset) / 2, 2)
                            secondBoardCheck = round((light1Offset + light2Offset) / 2, 2)
                            if self.finalCheckTimes == 1:
                                firstBoardError = round(firstBoardCheck - self.firstBoardLenBig, 2)
                                secondBoardError = round(secondBoardCheck - self.secondBoardLenBig, 2)
                                totalBoardError = round(firstBoardError + secondBoardError, 2)
                                frontAngleCheck = round(frontAngle + self.cutterTopMiddleAngle)
                                backAngleCheck = round(abs(backAngle) - abs(self.cutterBottomMiddleAngle), 2)
                            else:
                                firstBoardError = round(firstBoardCheck - self.secondBoardLenBig, 2)
                                secondBoardError = round(secondBoardCheck - self.thirdBoardLenBig, 2)
                                totalBoardError = round(firstBoardError + secondBoardError, 2)
                                frontAngleCheck = round(frontAngle + self.twoMiddleAngle, 2)
                                backAngleCheck = round(abs(backAngle) - abs(self.bottomMiddleAngle02), 2)
                            self.logger.debug("id_{} 大铡刀第{}次终点检测: 2号相机:3号灯管={:.2f},4号灯管={:.2f},第一块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                                self.bigCutterZmcIndex, self.finalCheckTimes, light3Offset, light4Offset, firstBoardCheck, frontAngleCheck,
                                firstBoardError))
                            self.logger.debug("id_{} 大铡刀第{}次终点检测: 1号相机:1号灯管={:.2f},2号灯管={:.2f},第二块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                                self.bigCutterZmcIndex, self.finalCheckTimes, light1Offset, light2Offset, secondBoardCheck, backAngleCheck,
                                secondBoardError))
                            if not self.boardBreak:
                                # 如果不是易断板
                                if ((abs(frontAngleCheck) > self.finalFrontAngleBig and self.finalCheckTimes == 1) or
                                    (abs(firstBoardError) > self.finalFirstBoardThresBig and self.finalCheckTimes == 1) or
                                    (abs(backAngleCheck) > self.finalBackAngleBig and self.finalCheckTimes == 2) or
                                    (abs(secondBoardError) > self.finalFirstBoardThresBig and self.finalCheckTimes == 2)
                                ) and not self.handCutBoardFlagBig:  # 每块板都进行二次调整,调整到一个固定的值
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError, totalBoardError)
                                    else:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整前,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError, totalBoardError)
                                    self.logger.debug(debugInfo)
                                    if (abs(frontAngleCheck) > self.finalFrontAngleBig and self.finalCheckTimes == 1) or \
                                            (abs(backAngleCheck) > self.finalBackAngleBig and self.finalCheckTimes == 2):
                                        # 终点检测,非第一块板长引起的,要给这个个信息发送给前端
                                        self.logger.debug("id_{} 终点检测: 验证出错,弹窗提示工人操作.".format(self.bigCutterZmcIndex))
                                        if abs(frontAngleCheck) > self.finalFrontAngleBig:
                                            self.frontImageSend = imgRes2
                                        else:
                                            self.frontImageSend = imgRes1
                                        self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                        self.finalCheckModifyBig = True
                                        while self.finalCheckModifyBig:
                                            gevent.sleep(0.5)
                                            continue
                                        if self.handCutBoardFlagBig:
                                            continue
                                        gevent.sleep(0.5)
                                        continue
                                    else:
                                        if not secondAdjust:
                                            if self.finalCheckTimes == 1:
                                                cutterFinalAdjust = -firstBoardError  # 第一次检测以第一块的误差为准
                                            else:
                                                cutterFinalAdjust = secondBoardError  # 第二次检测以第二块的误差为准
                                            self.logger.debug("id_{} 大铡刀第{}次终点检测: 进行二次调整,调整的值 = {:.2f},第一块误差 = {:.2f},第二块误差 = {:.2f}".format(
                                                self.bigCutterZmcIndex, self.finalCheckTimes, cutterFinalAdjust, firstBoardError, secondBoardError))
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_flag()
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            secondAdjust = True
                                            continue
                                        else:
                                            if self.finalCheckTimes == 1:
                                                debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后仍然没有通过.第一块偏差:{},阈值:{},第二块偏差:{},阈值:{}".format(
                                                    self.bigCutterZmcIndex, self.finalCheckTimes, firstBoardError, self.finalFirstBoardThresBig,
                                                    secondBoardError, self.finalSecondBoardThresBig)
                                            else:
                                                debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后仍然没有通过.第二块偏差:{},阈值:{},第三块偏差:{},阈值:{}".format(
                                                    self.bigCutterZmcIndex, self.finalCheckTimes, firstBoardError, self.finalFirstBoardThresBig,
                                                    secondBoardError, self.finalFirstBoardThresBig)
                                            self.logger.debug(debugInfo)
                                            self.frontImageSend = imgRes2
                                            self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                            self.finalCheckModifyBig = True
                                            while self.finalCheckModifyBig:
                                                gevent.sleep(0.5)
                                                continue
                                            if self.handCutBoardFlagBig:
                                                continue
                                            gevent.sleep(0.5)
                                            continue
                                # 如果验证通过
                                else:
                                    manualInfo = "人工确认" if self.handCutBoardFlagBig else "非人工确认"
                                    if self.handCutBoardFlagBig:
                                        self.handCutBoardFlagBig = False
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError,
                                            totalBoardError, manualInfo)
                                    else:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整前,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError,
                                            totalBoardError, manualInfo)
                                    secondAdjust = False  # 验证通过,把二次调整的bit位置位False
                                    self.logger.debug(debugInfo)
                                    ret = self.bigCutterZmc.set_final_check_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    # 然后就是分时第一次检测还是第二次检测
                                    if self.finalCheckTimes == 1:
                                        b = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_01",
                                             "firstBoardLenSmall": self.firstBoardLenSmall,
                                             "secondBoardLenSmall": self.secondBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle01,
                                             "rightMidAngleSmall": self.rightMiddleAngle01,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(b)
                                        # 然后将第二次要移动的距离写入
                                        ret = self.bigCutterZmc.set_second_check_move_distance(self.secondBoardLenBig)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                            return
                                    else:
                                        c = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_02",
                                             "firstBoardLenSmall": self.thirdBoardLenSmall,
                                             "secondBoardLenSmall": self.forthBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle02,
                                             "rightMidAngleSmall": self.rightMiddleAngle02,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(c)

                                        d = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_03",
                                             "firstBoardLenSmall": self.fifthBoardLenSmall,
                                             "secondBoardLenSmall": self.sixthBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle03,
                                             "rightMidAngleSmall": self.rightMiddleAngle03,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(d)

                                    self.logger.debug("id_{} 大铡刀{}次终点检测后下发小铡刀抓板数据:板长:{:.2f},角度：{:.2f}".format(
                                        self.bigCutterZmcIndex, self.finalCheckTimes, firstBoardCheck, self.twoCutterAngleOffset))
                                    ret = self.smallCutterZmc.set_board_len_small_offset(firstBoardCheck)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    ret = self.smallCutterZmc.set_angle_len_small_offset(self.twoCutterAngleOffset)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    self.logger.debug("id_{} 大铡刀第{}次终检完成铡板,底层角度补偿写入成功,补偿角度:{:.2f},此时的cutterQ={}".format(
                                        self.bigCutterZmcIndex, self.finalCheckTimes, self.cutterAngleOffset, self.cutterQueue.qsize()))
                                    # 如果验证通过
                                    if self.finalCheckTimes == 1:
                                        self.finalCheckTimes = 2
                                        self.finalCheckFlagBig = True
                                    else:
                                        self.finalCheckTimes = 1
                                        self.finalCheckFlagBig = False
                            # 如果是易断板
                            else:
                                # 如果不是易断板
                                if ((abs(frontAngleCheck) > self.finalFrontAngleBig and self.finalCheckTimes == 1) or
                                    (abs(firstBoardError) > self.finalFirstBoardThresBig and self.finalCheckTimes == 1) or
                                    (abs(backAngleCheck) > self.finalBackAngleBig and self.finalCheckTimes == 2) or
                                    (abs(secondBoardError) > self.finalFirstBoardThresBig and self.finalCheckTimes == 2)
                                ) and (not self.handCutBoardFlagBig):  # 每块板都进行二次调整,调整到一个固定的值
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError, totalBoardError)
                                    else:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整前,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError, totalBoardError)
                                    self.logger.debug(debugInfo)
                                    if (abs(frontAngleCheck) > self.finalFrontAngleBig and self.finalCheckTimes == 1) or \
                                            (abs(backAngleCheck) > self.finalBackAngleBig and self.finalCheckTimes == 2):
                                        # 终点检测,非第一块板长引起的,要给这个个信息发送给前端
                                        self.logger.debug("id_{} 终点检测: 验证出错,弹窗提示工人操作.".format(self.bigCutterZmcIndex))
                                        if abs(frontAngleCheck) > self.finalFrontAngleBig:
                                            self.frontImageSend = imgRes2
                                        else:
                                            self.frontImageSend = imgRes1
                                        self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                        self.finalCheckModifyBig = True
                                        while self.finalCheckModifyBig:
                                            gevent.sleep(0.5)
                                            continue
                                        if self.handCutBoardFlagBig:
                                            continue
                                        gevent.sleep(0.5)
                                        continue
                                    else:
                                        if not secondAdjust:
                                            if self.finalCheckTimes == 1:
                                                cutterFinalAdjust = -firstBoardError  # 第一次检测以第一块的误差为准
                                            else:
                                                cutterFinalAdjust = secondBoardError  # 第二次检测以第二块的误差为准
                                            self.logger.debug("id_{} 大铡刀第{}次终点检测: 进行二次调整,调整的值 = {:.2f},第一块误差 = {:.2f},第二块误差 = {:.2f}".format(
                                                self.bigCutterZmcIndex, self.finalCheckTimes, cutterFinalAdjust, firstBoardError, secondBoardError))
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            ret = self.bigCutterZmc.set_final_check_second_adjust_flag()
                                            if ret != 0:
                                                self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                                return
                                            secondAdjust = True
                                            continue
                                        else:
                                            debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后仍然没有通过.第一块偏差:{},阈值:{},第二块偏差:{},阈值:{}".format(
                                                self.bigCutterZmcIndex, self.finalCheckTimes, firstBoardError, self.firstBoardErrorThres,
                                                secondBoardError, self.firstBoardErrorThres)
                                            self.logger.debug(debugInfo)
                                            self.frontImageSend = imgRes2
                                            self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo)
                                            self.finalCheckModifyBig = True
                                            while self.finalCheckModifyBig:
                                                gevent.sleep(0.5)
                                                continue
                                            if self.handCutBoardFlagBig:
                                                continue
                                            gevent.sleep(0.5)
                                            continue
                                # 如果验证通过
                                else:
                                    manualInfo = "人工确认" if self.handCutBoardFlagBig else "非人工确认"
                                    if self.handCutBoardFlagBig:
                                        self.handCutBoardFlagBig = False
                                    if secondAdjust:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整后,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError,
                                            totalBoardError, manualInfo)
                                    else:
                                        debugInfo = "id_{} 大铡刀第{}次终点检测: 二次调整前,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{},非易端板,{} ".format(
                                            self.bigCutterZmcIndex, self.finalCheckTimes, frontAngleCheck, backAngleCheck, firstBoardError,
                                            secondBoardError,
                                            totalBoardError, manualInfo)
                                    secondAdjust = False
                                    self.logger.debug(debugInfo)
                                    ret = self.bigCutterZmc.set_final_check_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    # 然后就是分时第一次检测还是第二次检测
                                    if self.finalCheckTimes == 1:
                                        b = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_01",
                                             "firstBoardLenSmall": self.firstBoardLenSmall,
                                             "secondBoardLenSmall": self.secondBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle01,
                                             "rightMidAngleSmall": self.rightMiddleAngle01,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(b)
                                        # 然后将第二次要移动的距离写入
                                        ret = self.bigCutterZmc.set_second_check_move_distance(self.secondBoardLenBig)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
                                            return
                                    else:

                                        c = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_02",
                                             "firstBoardLenSmall": self.thirdBoardLenSmall,
                                             "secondBoardLenSmall": self.forthBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle02,
                                             "rightMidAngleSmall": self.rightMiddleAngle02,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(c)

                                        d = {"cutterIndexSmall": str(self.bigCutterZmcIndex) + "_03",
                                             "firstBoardLenSmall": self.fifthBoardLenSmall,
                                             "secondBoardLenSmall": self.sixthBoardLenSmall,
                                             "leftMidAngleSmall": self.leftMiddleAngle03,
                                             "rightMidAngleSmall": self.rightMiddleAngle03,
                                             "twoCutterOffset": self.twoCutterAngleOffset}
                                        self.cutterQueue.put(d)

                                    self.logger.debug("id_{} 大铡刀{}次终点检测后下发小铡刀抓板数据:板长:{:.2f},角度：{:.2f}".format(
                                        self.bigCutterZmcIndex, self.finalCheckTimes, firstBoardCheck, self.twoCutterAngleOffset))
                                    ret = self.smallCutterZmc.set_board_len_small_offset(firstBoardCheck)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    ret = self.smallCutterZmc.set_angle_len_small_offset(self.twoCutterAngleOffset)
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                        return
                                    self.logger.debug("id_{} 大铡刀第{}次终检完成铡板,底层角度补偿写入成功,补偿角度:{:.2f},此时的cutterQ={}".format(
                                        self.bigCutterZmcIndex, self.finalCheckTimes, self.cutterAngleOffset, self.cutterQueue.qsize()))
                                    # 如果验证通过
                                    if self.finalCheckTimes == 1:
                                        self.finalCheckTimes = 2
                                        self.finalCheckFlagBig = True
                                    else:
                                        self.finalCheckTimes = 1
                                        self.finalCheckFlagBig = False
                        else:
                            gevent.sleep(0.3)
                            continue
                    else:
                        gevent.sleep(0.3)
                        continue

            else:
                gevent.sleep(0.3)
                continue

    def check_take_board_task(self):
        """
        检测小铡刀取板信号的任务,这个任务之所以要单独出来,因为这个信号可能会跟肖铡刀的终检任务那里重合
        :return:
        """
        self.logger.debug("小铡刀取板信号检测任务函数开启")
        self.smallCutterZmc.set_allow_take_board_clear()  # 清除取板信号
        self.cutterQueueSmall = queue.Queue()
        while True:
            if self.deviceStates.workStopFlag:
                self.logger.debug("workStopFlag = True,小铡刀取板信号检测任务函数退出.")
                return
            ret, val = self.smallCutterZmc.get_allow_take_board_state()
            if val == 1:
                self.smallCutterZmc.set_allow_take_board_clear()  # 清空信号
                self.logger.debug("id_{} 小铡刀: 检测到抓板信号(modbus_bit(65) = 1),从大铡刀那里获取数据".format(self.bigCutterZmcIndex))
                if self.cutterQueue.empty():
                    self.logger.debug("id_{} 小铡刀: 大铡刀数据队列为空,小铡刀数据获取失败".format(self.bigCutterZmcIndex))
                    self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                    return
                else:
                    self.cutterQueueSmall = queue.Queue()
                    data = self.cutterQueue.get()  # 将大铡刀的数据获取到
                    self.cutterQueueSmall.put(data)
            else:
                gevent.sleep(0.2)
                continue

    def small_cutter_zmc_task(self):
        """
        后铡刀作业函数
        :return:
        """
        self.logger.debug("小铡刀作业任务函数开启")
        self.finalCheckFlagSmall = False
        self.beginCheckModifySmall = False
        self.beginCheckAdjustFlagSmall = False
        self.finalCheckModifySmall = False
        self.manualBeginCheckAngleOkSmall = False  # 起点检测人工确认角度OK
        self.beginCheckAgainSmall = False  # 小铡刀起点检测重新检测
        self.handCutBoardFlagSmall = False  # 小铡刀人工确认铡板
        self.handCutExReset = False  # 小铡刀异常复位，重新进入流程
        while True:
            self.handCutExReset = False
            if self.deviceStates.workStopFlag:
                self.logger.debug("workStopFlag = True,小铡刀作业任务函数退出.")
                return
            ret, val = self.smallCutterZmc.get_allow_take_pic_begin_check()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                return
            if val == 1:
                # 每次收到检测的时候,都打开门报警
                newData = {
                    "cutterZmcIndex": self.bigCutterZmcIndex
                }
                self.update_working_info_to_db_and_web(newData)
                self.smallCutterZmc.set_allow_take_pic_begin_check_clear()

                if self.beginCheckAdjustFlagSmall or self.beginCheckAgainSmall or self.manualBeginCheckAngleOkSmall:
                    if self.beginCheckAgainSmall:
                        self.beginCheckAgainSmall = False
                        self.logger.debug("id_{} 小铡刀: 界面上点击了重新检测".format(self.bigCutterZmcIndex))
                    if self.manualBeginCheckAngleOkSmall:
                        self.logger.debug("id_{} 小铡刀: 界面上点击了角度确认OK".format(self.bigCutterZmcIndex))

                else:
                    if self.cutterQueueSmall.empty():
                        ret, val = self.smallCutterZmc.get_allow_take_board_state()
                        if val == 1:
                            self.smallCutterZmc.set_allow_take_board_clear()  # 清空信号
                            self.logger.debug("id_{} 小铡刀: 检测到抓板信号(modbus_bit(65) = 1),从大铡刀那里获取数据".format(self.bigCutterZmcIndex))
                            if self.cutterQueue.empty():
                                self.logger.debug("id_{} 小铡刀: 大铡刀数据队列为空,小铡刀数据获取失败".format(self.bigCutterZmcIndex))
                                self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
                                return
                            else:
                                self.cutterQueueSmall = queue.Queue()
                                data = self.cutterQueue.get()  # 将大铡刀的数据获取到
                                self.cutterQueueSmall.put(data)
                    if not self.cutterQueueSmall.empty():
                        # 取数据之前,先判断有没有数据
                        cutter_data = self.cutterQueueSmall.get()
                        self.smallCutterIndex = cutter_data['cutterIndexSmall']
                        cutterAngleOffset = cutter_data["twoCutterOffset"]
                        ret = self.smallCutterZmc.set_angle_offset(cutterAngleOffset)
                        if ret != 0:
                            self.keep_zmc_read_write_error('set small_cutter 124 failed.后铡刀控制器通信异常,请检查电源线和网线!', "smallCutterZmc",
                                                           self.bigCutterZmcIndex)
                            return
                        self.logger.debug("id_{} 从队列中拿出数据,此时的 大铡刀的队列数据 的size = {},小铡刀的队列数据的size={}".format(self.smallCutterIndex,
                                                                                                                                        self.cutterQueue.qsize(),
                                                                                                                                        self.cutterQueueSmall.qsize()))
                        self.logger.debug("id_{} 取出来的数据: {}".format(self.smallCutterIndex, cutter_data))
                        self.firstBoardReal = cutter_data['firstBoardLenSmall']  # 第一块板长
                        self.secondBoardLenReal = cutter_data['secondBoardLenSmall']  # 总板长
                        self.firstLineMiddleSmall = cutter_data["rightMidAngleSmall"]
                        self.thirdMiddleLineSmall = cutter_data["leftMidAngleSmall"]
                self.logger.debug("id_{} 小铡刀起点检测: 收到拍照信号,1号相机开始拍照".format(self.smallCutterIndex))
                self.smallCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
                self.cutterImageSmall1 = None
                res, self.cutterImageSmall1 = self.smallCutterCamCal.get_cutter_image(1)
                if res != "ok":
                    self.logger.debug("id_{} 小铡刀起点检测: 1号相机拍照失败,重新打开相机开始拍照".format(self.smallCutterIndex))
                    res, self.cutterImageSmall1 = self.smallCutterCamCal.get_cutter_image(1)
                    if res != "ok":
                        self.keep_zmc_read_write_error(self.cutterImageSmall1, "cameraError", self.smallCutterIndex)
                        return
                endwith = "adjust" if self.beginCheckAdjustFlagSmall else "first"
                light1First, light2First, imageRes = get_first_thres_point_begain_check(self.cutterImageSmall1, self.smallCutterCamCal.light1Pos,
                                                                                        self.smallCutterCamCal.light2Pos)
                save_small_begin_check_image(self.smallCutterIndex, self.cutterImageSmall1, endwith=endwith)
                save_small_begin_check_res_image(self.smallCutterIndex, imageRes, endwith=endwith)
                if light1First is None or light2First is None:
                    cutterHintInfo = "小铡刀有灯管全黑,这个时候考虑是冲板,铡刀后移50个mm,再检测一次."
                    self.logger.debug("id_{} 起点检测: {}".format(self.smallCutterIndex, cutterHintInfo))
                    self.smallCutterZmc.move_x(-50)
                    gevent.sleep(1)
                    res, self.cutterImageSmall1 = self.smallCutterCamCal.get_cutter_image(1)
                    light1First, light2First, imageRes = get_first_thres_point_begain_check(self.cutterImageSmall1,
                                                                                            self.smallCutterCamCal.light1Pos,
                                                                                            self.smallCutterCamCal.light2Pos)
                    save_small_begin_check_image(self.smallCutterIndex, self.cutterImageSmall1, endwith=endwith)
                    save_small_begin_check_res_image(self.smallCutterIndex, imageRes, endwith=endwith)
                    if light1First is None or light2First is None:
                        cutterHintInfo = "小铡刀后退了50个mm依旧检测到有黑色的灯管,弹框提示工人操作"
                        self.logger.debug("id_{} 小铡刀起点检测: {}".format(self.smallCutterIndex, cutterHintInfo))
                        self.beginCheckModifySmall = True
                        self.send_small_cutter_begin_check_modal_to_web(imageRes, cutterHintInfo)
                        while self.beginCheckModifySmall:
                            gevent.sleep(0.3)
                            continue
                        if ec.eapOnline:
                            request_alarm_report(AlarmType.R, 13)
                        if self.handCutExReset:
                            self.handCutExReset = False
                            continue
                        gevent.sleep(0.5)
                        continue

                light1Offset, light2Offset, angleCheck = self.smallCutterCamCal.get_offset_to_cutter_by_ruler(1, light1First, light2First)
                angleAdjust = round(angleCheck + self.firstLineMiddleSmall, 2)
                self.logger.debug("id_{} 小铡刀起点检测: 1号灯管 = {},2号灯管 = {},角度: check = {},topM = {},sum = {},角度补偿 = {}".format(
                    self.smallCutterIndex, light1Offset, light2Offset, angleCheck, self.firstLineMiddleSmall, angleAdjust, self.beginAngleOffsetSmall))
                # 加上角度补偿值:
                angleAdjustReal = angleAdjust + self.beginAngleOffsetSmall
                if abs(angleAdjustReal) > self.beginAngleThresSmall and (not self.manualBeginCheckAngleOkSmall):
                    if not self.beginCheckAdjustFlagSmall:
                        ret = self.smallCutterZmc.set_begin_check_angle_offset(angleAdjustReal)
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                            return
                        ret = self.smallCutterZmc.set_begin_check_angle_fail()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                            return
                        self.logger.debug("id_{} 小铡刀起点检测: 验证失败,进行角度调整,调整角度 = {}".format(self.smallCutterIndex, angleAdjust))
                        self.beginAngleThresSmall += 0.1
                        self.beginCheckAdjustFlagSmall = True
                        gevent.sleep(0.05)
                        continue
                    else:
                        # 如果这里调整完之后,检测依旧没有通过,人工弹窗提示工人进行操作.正值逆时针调整,负值顺时针调整
                        if angleAdjustReal > 0:
                            cutterHintInfo = "id_{} 小铡刀起点检测: 角度调整完之后,依旧有角度,请人工逆时针调整,角度 = {:.2f}".format(self.smallCutterIndex, angleAdjustReal)
                        else:
                            cutterHintInfo = "id_{} 小铡刀起点检测: 角度调整完之后,依旧有角度,请人工调整顺时针调整,角度 = {:.2f}".format(self.smallCutterIndex, angleAdjustReal)
                        self.logger.debug(cutterHintInfo)
                        self.beginCheckModifySmall = True
                        self.send_small_cutter_begin_check_modal_to_web(imageRes, cutterHintInfo)
                        while self.beginCheckModifySmall and not self.deviceStates.workStopFlag:
                            gevent.sleep(0.2)
                            continue
                        if ec.eapOnline:
                            request_alarm_report(AlarmType.R, 13)
                        if self.handCutBoardFlagSmall:
                            continue
                        if self.handCutExReset:
                            self.handCutExReset = False
                            continue
                        gevent.sleep(0.5)
                        continue
                else:
                    manualInfo = "人工确认" if self.manualBeginCheckAngleOkSmall else "非人工确认"
                    if self.manualBeginCheckAngleOkSmall:
                        self.manualBeginCheckAngleOkSmall = False
                    beginCheckToCutter = round((light1Offset + light2Offset) / 2, 2)
                    cutterMoveDis = round(beginCheckToCutter + self.firstBoardReal + self.cutterMoveOffsetSmall, 2)
                    ret = self.smallCutterZmc.set_begin_check_move_distance(cutterMoveDis)
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                        return
                    ret = self.smallCutterZmc.set_begin_check_angle_ok()
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                        return
                    self.logger.debug("id_{} 小铡刀起点检测:{}, 验证成功,角度 = {:.2f},角度补偿 = {:.2f},板边到铡刀距离:{},第一块板长:{},移动距离:{},移动补偿:{}".format(
                        self.smallCutterIndex, manualInfo, angleAdjust, self.beginAngleOffsetSmall, beginCheckToCutter, self.firstBoardReal, cutterMoveDis,
                        self.cutterMoveOffsetSmall))
                    self.beginCheckAdjustFlagSmall = False
                    self.finalCheckFlagSmall = True
                    self.reload_cutter_cam_check_thres_small()

                self.light_keep_Exception = 1
                secondAdjust = False  # 是否进行了二次调整的标志.
                while self.finalCheckFlagSmall:
                    if self.deviceStates.workStopFlag:
                        self.logger.debug("id_{} workStopFlag = True,铡刀作业任务函数退出.".format(self.camZmcIndex))
                        return
                    ret, val = self.smallCutterZmc.get_allow_take_pic_final_check()
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                        return
                    if val == 1:
                        self.smallCutterZmc.set_allow_take_pic_final_check_clear()
                        self.logger.debug("id_{} 小铡刀终点检测: 收到拍照信号,开始拍照".format(self.smallCutterIndex))
                        res, self.cutterImageSmall1 = self.smallCutterCamCal.get_cutter_image(1)
                        if res != "ok":
                            self.logger.debug("id_{} 小铡刀终点检测: 1号相机拍照失败,重新打开相机开始拍照".format(self.smallCutterIndex))
                            res, self.cutterImageSmall1 = self.smallCutterCamCal.get_cutter_image(1)
                            if res != "ok":
                                self.keep_zmc_read_write_error(self.cutterImageSmall1, "cameraError", self.smallCutterIndex)
                                return
                        res, self.cutterImageSmall2 = self.smallCutterCamCal.get_cutter_image(2)
                        if res != "ok":
                            self.logger.debug("id_{} 小铡刀终点检测: 2号相机拍照失败,重新打开相机开始拍照".format(self.smallCutterIndex))
                            res, self.cutterImageSmall2 = self.smallCutterCamCal.get_cutter_image(2)
                            if res != "ok":
                                self.keep_zmc_read_write_error(self.cutterImageSmall2, "cameraError", self.smallCutterIndex)
                                return
                        finalLight1First, finalLight2First, imgRes1 = get_first_thres_point_final_check_cam_1(self.cutterImageSmall1,
                                                                                                              self.smallCutterCamCal.light1Pos,
                                                                                                              self.smallCutterCamCal.light2Pos)
                        finalLight3First, finalLight4First, imgRes2 = get_first_thres_point_final_check_cam_2(self.cutterImageSmall2,
                                                                                                              self.smallCutterCamCal.light3Pos,
                                                                                                              self.smallCutterCamCal.light4Pos)
                        # 保存图片
                        save_small_final_check_image(self.smallCutterIndex, self.cutterImageSmall1, self.cutterImageSmall2)
                        save_small_final_check_image_res(self.smallCutterIndex, imgRes1, imgRes2)

                        if (finalLight1First is None or finalLight2First is None or finalLight3First is None or finalLight4First is None) \
                                and (not self.handCutBoardFlagSmall):
                            if finalLight1First is None or finalLight2First is None:
                                self.smallImageSend = imgRes1
                            else:
                                self.smallImageSend = imgRes2
                            cutterHintInfo = "id_{} 小铡刀终点检测: 检测到某个灯管全黑,请人工确认!"
                            self.logger.debug(cutterHintInfo)
                            self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, cutterHintInfo)
                            self.finalCheckModifySmall = True
                            while self.finalCheckModifySmall:
                                gevent.sleep(0.5)
                                continue
                            if self.handCutExReset:
                                self.handCutExReset = False
                                continue
                            gevent.sleep(0.5)
                            continue

                        # 如果找到了灯管的遮挡位置,就开始计算距离和角度
                        light1Offset, light2Offset, backAngle = self.smallCutterCamCal.get_offset_to_cutter_by_ruler(1, finalLight1First,
                                                                                                                     finalLight2First)
                        light3Offset, light4Offset, frontAngle = self.smallCutterCamCal.get_offset_to_cutter_by_ruler(2, finalLight3First,
                                                                                                                      finalLight4First)
                        firstBoardCheck = round((light3Offset + light4Offset) / 2, 2)
                        frontAngleCheck = round(frontAngle + self.firstLineMiddleSmall, 2)
                        secondBoardCheck = round((light1Offset + light2Offset) / 2, 2)
                        backAngleCheck = round(abs(backAngle) - abs(self.thirdMiddleLineSmall), 2)
                        firstBoardError = round(firstBoardCheck - self.firstBoardReal, 2)
                        secondBoardError = round(secondBoardCheck - self.secondBoardLenReal, 2)
                        totalBoardError = round(firstBoardError + secondBoardError, 2)
                        self.logger.debug("id_{} 小铡刀终点检测: 2号相机:3号灯管={:.2f},4号灯管={:.2f},第一块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                            self.smallCutterIndex, light3Offset, light4Offset, firstBoardCheck, frontAngleCheck, firstBoardError))
                        self.logger.debug("id_{} 小铡刀终点检测: 1号相机:1号灯管={:.2f},2号灯管={:.2f},第二块板长={:.2f},角度={:.2f},误差={:.2f}".format(
                            self.smallCutterIndex, light1Offset, light2Offset, secondBoardCheck, backAngleCheck, secondBoardError))

                        # 检测时，灯管被遮挡，重新检测一次
                        if abs(secondBoardError) > 50 and self.light_keep_Exception == 1:
                            self.logger.debug("id_{} 小铡刀终点检测: 检测到灯管被遮挡；重新进行检测")
                            self.smallCutterZmc.set_allow_take_pic_final_check()
                            self.light_keep_Exception += 1
                            gevent.sleep(1)
                            continue
                        self.light_keep_Exception = 1

                        if not self.boardBreak:
                            # 如果不是易断板
                            if (abs(frontAngleCheck) > self.finalFrontAngleSmall or abs(firstBoardError) > self.finalFirstBoardThresSmall or
                                abs(backAngleCheck) > self.finalBackAngleSmall or abs(secondBoardError) > self.finalSecondBoardThresSmall
                            ) and (not self.handCutBoardFlagSmall):  # 每块板都进行二次调整,调整到一个固定的值
                                if secondAdjust:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整后,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                else:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整前,验证失败,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                self.logger.debug(debugInfo)
                                if abs(frontAngleCheck) > self.finalFrontAngleSmall or abs(backAngleCheck) > self.finalBackAngleSmall:
                                    # 终点检测,非第一块板长引起的,要给这个个信息发送给前端
                                    self.logger.debug("id_{} 终点检测: 验证出错,弹窗提示工人操作.".format(self.smallCutterIndex))
                                    if abs(frontAngleCheck) > self.finalFrontAngleSmall:
                                        self.smallImageSend = imgRes2
                                    else:
                                        self.smallImageSend = imgRes1
                                    self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, debugInfo)
                                    self.finalCheckModifySmall = True
                                    while self.finalCheckModifySmall:
                                        gevent.sleep(0.5)
                                        continue
                                    if self.handCutExReset:
                                        self.handCutExReset = False
                                        continue
                                    gevent.sleep(0.5)
                                    continue
                                else:
                                    if not secondAdjust:
                                        cutterFinalAdjust = -firstBoardError  # 加上二次调整的补偿值.
                                        self.logger.debug("id_{} 小铡刀终点检测: 进行二次调整,调整的值 = {:.2f},第一块误差 = {:.2f}".format(self.smallCutterIndex,
                                                                                                                                            cutterFinalAdjust,
                                                                                                                                            firstBoardError))
                                        ret = self.smallCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                            return
                                        ret = self.smallCutterZmc.set_final_check_second_adjust_flag()
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                            return
                                        secondAdjust = True
                                        continue
                                    else:
                                        debugInfo = "id_{} 小铡刀终点检测: 二次调整后仍然没有通过.第一块偏差:{},阈值:{}".format(
                                            self.smallCutterIndex, firstBoardError, self.firstBoardErrorThres)
                                        self.logger.debug(debugInfo)
                                        self.smallImageSend = imgRes2
                                        self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, debugInfo)
                                        self.finalCheckModifySmall = True
                                        while self.finalCheckModifySmall:
                                            gevent.sleep(0.5)
                                            continue
                                        if self.handCutBoardFlagSmall:
                                            continue
                                        if self.handCutExReset:
                                            self.handCutExReset = False
                                            continue
                                        gevent.sleep(0.5)
                                        continue
                            # 如果验证通过
                            else:
                                manualInfo = "人工确认" if self.handCutBoardFlagSmall else "非人工确认"
                                if self.handCutBoardFlagSmall:
                                    self.handCutBoardFlagSmall = False
                                if secondAdjust:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整后,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} 非易断板,{} ".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                else:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整前,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} 非易断板,{}".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                self.logger.debug(debugInfo)
                                ret = self.smallCutterZmc.set_final_check_result_ok()
                                # 如果是第二块板子
                                if "_02" in self.smallCutterIndex:
                                    try:
                                        response = eap_request.request_job_count_report(JobCountType.Out)
                                        response_parse.parse_job_count_report_response(response)
                                    except Exception as e:
                                        logger.debug(str(e))
                                if ret != 0:
                                    self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                    return
                                else:
                                    self.finalCheckFlagSmall = False
                                    self.finalCheckModifySmall = False

                        # 如果是易断板
                        else:
                            if ((abs(frontAngleCheck) > self.finalFrontAngleSmall) or abs(firstBoardError) > self.finalFirstBoardThresSmall or
                                secondBoardError < -(self.finalSecondBoardThresSmall - 3)) and (not self.handCutBoardFlagSmall):
                                if secondAdjust:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整后,验证失败,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                else:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整前,验证失败,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{} ".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError)
                                self.logger.debug(debugInfo)
                                if abs(frontAngleCheck) > self.finalFrontAngleSmall:
                                    cutterHintInfo = "id_{} 小铡刀终点检测: 易断板,前角超过阈值.检测值: {},阈值: {}".format(self.smallCutterIndex, frontAngleCheck,
                                                                                                                            self.finalFrontAngleSmall)
                                    self.logger.debug(cutterHintInfo)
                                    self.smallImageSend = imgRes2
                                    self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, cutterHintInfo)
                                    self.finalCheckModifySmall = True
                                    while self.finalCheckModifySmall:
                                        gevent.sleep(0.3)
                                        continue
                                    if self.handCutExReset:
                                        self.handCutExReset = False
                                        continue
                                    gevent.sleep(0.3)
                                    continue
                                elif (secondBoardError + firstBoardError) < -self.finalFoldThresSmall:
                                    cutterHintInfo = "id_{} 小铡刀终点检测: 易断板,检测到叠板.检测值: {},阈值: {}".format(self.smallCutterIndex,
                                                                                                                          secondBoardError, self.finalFoldThresSmall)
                                    self.logger.debug(cutterHintInfo)
                                    self.smallImageSend = imgRes1
                                    self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, cutterHintInfo)
                                    self.finalCheckModifySmall = True
                                    while self.finalCheckModifySmall:
                                        gevent.sleep(0.3)
                                        continue
                                    if self.handCutExReset:
                                        self.handCutExReset = False
                                        continue
                                    gevent.sleep(0.3)
                                    continue
                                else:
                                    if not secondAdjust:
                                        cutterFinalAdjust = -firstBoardError
                                        self.logger.debug("id_{} 小铡刀终点检测: 易断板,进行二次调整,调整的值 = {:.2f},第一块板误差 = {:.2f}".format(self.smallCutterIndex,
                                                                                                                                                     cutterFinalAdjust,
                                                                                                                                                     -firstBoardError))
                                        ret = self.smallCutterZmc.set_final_check_second_adjust_distance(cutterFinalAdjust)
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                            return
                                        ret = self.smallCutterZmc.set_final_check_second_adjust_flag()
                                        if ret != 0:
                                            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                            return
                                        secondAdjust = True
                                        continue
                                    else:
                                        debugInfo = "id_{} 小铡刀终点检测: 易断板,二次调整后仍然没有通过.第一块偏差:{},阈值:{}".format(
                                            self.smallCutterIndex, firstBoardError, self.firstBoardErrorThres)
                                        self.logger.debug(debugInfo)
                                        self.smallImageSend = imgRes2
                                        self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, debugInfo)
                                        self.finalCheckModifySmall = True
                                        while self.finalCheckModifySmall:
                                            gevent.sleep(0.5)
                                            continue
                                        if self.handCutBoardFlagSmall:
                                            continue
                                        if self.handCutExReset:
                                            self.handCutExReset = False
                                            continue
                                        gevent.sleep(0.5)
                                        continue

                            else:
                                manualInfo = "人工确认" if self.handCutBoardFlagSmall else "非人工确认"
                                if self.handCutBoardFlagSmall:
                                    self.handCutBoardFlagSmall = False
                                if secondAdjust:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整后,易断板,验证通过,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{}, {}".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                else:
                                    debugInfo = "id_{} 小铡刀终点检测: 二次调整前,验证通过,易断板,前角:{},后角:{},第一块偏:{},第二块偏:{},总偏差:{}, {}".format(
                                        self.smallCutterIndex, frontAngleCheck, backAngleCheck, firstBoardError, secondBoardError, totalBoardError, manualInfo)
                                self.logger.debug(debugInfo)
                                ret = self.smallCutterZmc.set_final_check_result_ok()
                                if ret != 0:
                                    self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.smallCutterIndex)
                                    return
                                else:
                                    self.finalCheckFlagSmall = False
                                    self.finalCheckModifySmall = False


                    else:
                        gevent.sleep(0.3)
                        continue

            else:
                gevent.sleep(0.3)
                continue

    def web_request_begin_check_again_big(self):
        """
        首检弹框那里,界面上点击了重新检测
        :return:
        """
        self.logger.debug("id_{} 大铡刀起点检测: 界面上点击了重新检测按钮".format(self.bigCutterZmcIndex))
        # self.smallCutterZmc.open_door_alarm()
        self.bigCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.bigCutterZmc.set_allow_begin_check_again_flag()
        gevent.sleep(0.3)
        self.beginCheckModifyBig = False
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
            return
        return "ok"

    def web_request_begin_check_again_small(self):
        """
        首检小铡刀弹窗
        :return:
        """
        self.smallCutterZmc.open_door_alarm()
        # self.bigCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.smallCutterZmc.set_allow_begin_check_again_flag()
        gevent.sleep(0.3)
        self.beginCheckModifySmall = False
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
            return
        return "ok"

    def web_request_begin_check_manual_ok_small(self):
        """
        小铡刀人工确认角度OK
        :return:
        """
        self.smallCutterZmc.open_door_alarm()
        # self.bigCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.smallCutterZmc.set_allow_begin_check_again_flag()
        gevent.sleep(0.3)
        self.beginCheckModifySmall = False
        self.manualBeginCheckAngleOkSmall = True
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.bigCutterZmcIndex)
            return
        return "ok"

    def web_request_begin_check_manual_ok_big(self):
        """
        大铡刀起点检测,人工确认角度OK
        :return:
        """
        self.logger.debug("id_{} 大铡刀起点检测: 人工确认角度OK!".format(self.bigCutterZmcIndex))
        # self.smallCutterZmc.open_door_alarm()
        self.bigCutterZmc.open_door_alarm()  # 免得某个地方又忘记关了.
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.bigCutterZmc.set_allow_begin_check_again_flag()
        gevent.sleep(0.3)
        self.beginCheckModifyBig = False
        self.beginCheckManualOkFlagBig = True  # 大铡刀起点检测,人工确认角度OK
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
            return
        return "ok"

    def web_request_final_cut_board_big(self):
        """
        前端界面上点击了人工确定大铡刀铡板
        :return:
        """
        resVal1, resVal2 = self.bigCutterZmc.get_door_start()
        if resVal1 != 1 or resVal2 != 1:
            self.logger.debug("id_{} 大铡刀终点检测: 界面上点击了人工确认铡板,检测到门没有关闭,弹窗提示工人关门!".format(self.bigCutterZmcIndex))
            debugInfo = "大铡刀防护门未关闭， 请确认门关闭之后，重新点击 人工确认铡板"
            self.send_front_cutter_final_check_modal_to_web(self.frontImageSend, debugInfo, fontStart=True)
        else:
            self.logger.debug("id_{} 大铡刀终点检测: 界面上点击了人工确认铡板,执行分板动作".format(self.bigCutterZmcIndex))
            # self.smallCutterZmc.open_door_alarm()
            self.bigCutterZmc.open_door_alarm()
            self.bigCutterZmc.close_buzzer_alarm()
            self.bigCutterZmc.set_allow_final_check_again_flag()
            gevent.sleep(0.3)
            self.handCutBoardFlagBig = True
            self.finalCheckModifyBig = False
            return "ok"

    def web_request_final_cut_board_small(self):
        """
        前端界面上点击了人工确定小铡刀铡板
        :return:
        """
        resVal1, resVal2 = self.smallCutterZmc.get_door_start()
        if resVal1 != 1 or resVal2 != 1:
            self.logger.debug("id_{} 小铡刀终点检测: 界面上点击了人工确认铡板,检测到门没有关闭,弹窗提示工人关门!".format(self.smallCutterIndex))
            debugInfo = "小铡刀防护门未关闭， 请确认门关闭之后，重新点击 人工确认铡板"
            self.send_small_cutter_final_check_modal_to_web(self.smallImageSend, debugInfo, fontStart=True)
        else:
            self.logger.debug("id_{} 小铡刀终点检测: 界面上点击了人工确认铡板,执行分板动作".format(self.smallCutterIndex))
            self.smallCutterZmc.open_door_alarm()
            # self.bigCutterZmc.open_door_alarm()
            self.bigCutterZmc.close_buzzer_alarm()
            self.handCutBoardFlagSmall = True
            self.finalCheckModifySmall = False
            ret = self.smallCutterZmc.set_allow_final_check_again_flag()
            gevent.sleep(0.3)
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.smallCutterIndex)
                return
            return "ok"

    def web_request_final_check_again_big(self):
        """
        大铡刀终检弹框那里,界面上点击了重新检测,终检这里重新检测一次
        :return:
        """
        self.logger.debug("id_{} 大铡刀终点检测: 界面上点击了重新检测按钮".format(self.bigCutterZmcIndex))
        # self.smallCutterZmc.open_door_alarm()
        self.bigCutterZmc.open_door_alarm()
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.bigCutterZmc.set_allow_final_check_again_flag()
        gevent.sleep(0.3)
        self.finalCheckModifyBig = False
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "bigCutterZmc", self.bigCutterZmcIndex)
            return
        return "ok"

    def web_request_final_check_again_small(self):
        """
        小铡刀终检弹框那里,界面上点击了重新检测,终检这里重新检测一次
        :return:
        """
        self.logger.debug("id_{} 小铡刀终点检测: 界面上点击了重新检测按钮".format(self.smallCutterIndex))
        self.smallCutterZmc.open_door_alarm()
        # self.bigCutterZmc.open_door_alarm()
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.smallCutterZmc.set_allow_final_check_again_flag()
        gevent.sleep(0.3)
        self.finalCheckModifySmall = False
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "smallCutterZmc", self.smallCutterIndex)
            return
        return "ok"

    def send_front_cutter_begin_check_modal_to_web(self, imageSend, info):
        """
        发送大铡刀首检出问题的提示框
        :param imageSend:
        :param info:
        :return:
        """
        newWidth, newHeight = 1000, 880
        imageSend = cv.resize(imageSend, (newWidth, newHeight), cv.INTER_AREA)
        msgVal = {
            "val": "bigBeginCheckError",
            "bigCutterImageSrc": common_tools.image_to_string(imageSend),
            "bigCutterHintInfo": info
        }
        self.bigCutterZmc.close_door_alarm()
        # self.smallCutterZmc.close_door_alarm()
        send_produce_state_to_ui(msgVal)
        # 打开蜂鸣器和灯光亮起来
        self.bigCutterZmc.open_buzzer_alarm()

    def send_small_cutter_begin_check_modal_to_web(self, imageSend, info):
        """
        发送小铡刀首检出问题的提示框
        :param imageSend:
        :param info:
        :return:
        """
        # 将铡刀的图片缩放为固定的长宽
        newWidth, newHeight = 1000, 880
        imageSend = cv.resize(imageSend, (newWidth, newHeight), cv.INTER_AREA)
        msgVal = {
            "val": "smallBeginCheckError",
            "smallCutterImageSrc": common_tools.image_to_string(imageSend),
            "smallCutterHintInfo": info
        }
        # self.bigCutterZmc.close_door_alarm()
        self.smallCutterZmc.close_door_alarm()
        send_produce_state_to_ui(msgVal)
        # 打开蜂鸣器和灯光亮起来
        self.bigCutterZmc.open_buzzer_alarm()
        # 发送给Eap警报
        if ec.eapOnline:
            request_alarm_report(AlarmType.S,13)

    def send_front_cutter_final_check_modal_to_web(self, imageSend, info, fontStart=False):
        """
        发送大铡刀终检出问题的提示框
        :param imageSend:
        :param info:
        :param fontStart
        :return:
        """
        newWidth, newHeight = 1000, 880
        imageSend = cv.resize(imageSend, (newWidth, newHeight), cv.INTER_AREA)
        msgVal = {
            "val": "frontFinalCheckError",
            "bigCutterImageSrc": common_tools.image_to_string(imageSend),
            "bigCutterHintInfo": info,
            "bigFontStart": fontStart
        }
        self.bigCutterZmc.close_door_alarm()
        # self.smallCutterZmc.close_door_alarm()
        # 打开蜂鸣器和灯光亮起来
        self.bigCutterZmc.open_buzzer_alarm()
        send_produce_state_to_ui(msgVal)
        # 发送大铡刀Eap警报
        if ec.eapOnline:
            request_alarm_report(AlarmType.S, 12)

    def send_small_cutter_final_check_modal_to_web(self, imageSend, info, fontStart=False):
        """
        发送小铡刀终检出问题的提示框
        :param imageSend:
        :param info:
        :param fontStart
        :return:
        """
        newWidth, newHeight = 1000, 880
        imageSend = cv.resize(imageSend, (newWidth, newHeight), cv.INTER_AREA)
        msgVal = {
            "val": "smallFinalCheckError",
            "smallCutterImageSrc": common_tools.image_to_string(imageSend),
            "smallCutterHintInfo": info,
            "smallFontStart": fontStart
        }
        # self.bigCutterZmc.close_door_alarm()
        self.smallCutterZmc.close_door_alarm()
        # 打开蜂鸣器和灯光亮起来
        self.bigCutterZmc.open_buzzer_alarm()
        send_produce_state_to_ui(msgVal)

    def cbj_zmc_task(self):
        """
        发送切线的任务函数
        :return:
        """
        self.logger.debug("裁切机发送切线的任务函数开启")
        lastDragTime = 0
        while True:
            if self.deviceStates.workStopFlag:
                self.logger.debug("id_{} workStopFlag = True, 裁切机发送切线的任务函数退出".format(self.cbjZmcIndex))
                return
            ret, val = self.cbjZmc.get_allow_send_lines()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "cbjZmc", self.cbjZmcIndex)
                return
            if val == 1:
                # 收到发送切线的函数,开始发送切线
                self.cbjSendLinesTime = time.time()
                if not self.linesQueue.empty():
                    boardLine = self.linesQueue.get()
                    self.cbjZmcIndex = boardLine["boardIndex"]
                    newData = {
                        "cbjZmcIndex": self.cbjZmcIndex
                    }
                    self.update_working_info_to_db_and_web(newData)
                    linesSend = boardLine["lines"]
                    cutSpeed = boardLine["cutSpeed"]
                    firstPointX = boardLine["firstPointX"]
                    if self.jointNumber == "4":
                        boardLength = boardLine["firstBoardLenBig"] + boardLine["secondBoardLenBig"]
                    else:
                        boardLength = boardLine["firstBoardLenBig"] + boardLine["secondBoardLenBig"] + boardLine["thirdBoardLenBig"]
                    boardWidth = boardLine["cutWidth"]
                    self.logger.debug("id_{} 裁切机: get cbj modbus(25) = 1,收到发送切线信号,发送切线:{}".format(self.cbjZmcIndex, linesSend))
                    # 先将第一个点的坐标和板的长度发送到底层
                    ret = self.cbjZmc.set_table(87, 2, [firstPointX, boardLength])
                    if ret != 0:
                        self.keep_zmc_read_write_error(ret, "cbjZmc", self.cbjZmcIndex)
                        return
                    # 将是否切第三刀发送到底层
                    if not self.isThirdCut:
                        thirdCutNeeded = False
                    else:
                        thirdCutNeeded = True

                    self.cbjZmc.set_third_cut_needed(thirdCutNeeded)
                    # 获取最后一次反馈回来的坐标
                    self.logger.debug("id_{} 裁切机: 获取上一次切线反馈回来的坐标值".format(self.cbjZmcIndex))
                    res, lastData = self.cbjZmc.get_table(10000, 16)
                    for i in range(0, 16, 4):
                        self.logger.debug("id_{} 第 {} 条切线:({:.2f},{:.2f}),({:.2f},{:.2f})".format(
                            self.cbjZmcIndex, i // 4 + 1, lastData[i], lastData[i + 1], lastData[i + 2], lastData[i + 3]))
                    self.bigCutterZmc.set_cut_board_width(boardWidth / 2)
                    self.bigCutterZmc.set_cut_board_width_finish()
                    self.logger.debug("id_{} 裁切机: 设置板宽和允许吹气完成,设置的板宽的一半:{:.2f}".format(self.cbjZmcIndex, boardWidth / 2))
                    lineList = []  # 要发送的切线
                    pointsNumber = len(linesSend)
                    for i in range(0, pointsNumber, 2):
                        lineList.append([linesSend[i], linesSend[i + 1]])
                    # 获取第一刀的切割速度
                    speedList = []
                    for i in range(len(lineList)):
                        if i == 0:
                            speedList.append(self.firstCutSpeed)
                        else:
                            speedList.append(cutSpeed)
                    knifeAngleList = boardLine["knifeAngleList"]
                    res, info = self.cbjZmc.set_lines_to_cbj_with_capfile(lineList, speedList, self.cutDeep, knifeAngleList, self.cbjZmcIndex)
                    if res != "ok":
                        self.logger.debug("id_{} 裁切机: 切线发送失败: {}".format(self.cbjZmcIndex, info))
                        self.keep_zmc_read_write_error(info, "cbjZmc", self.cbjZmcIndex)
                        return
                    else:
                        ret = self.cbjZmc.set_cut_lines_send_finish()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "cbjZmc", self.cbjZmcIndex)
                            return
                        self.logger.debug("id_{} 裁切机: 设置裁切机控制器切线发送完毕.".format(self.cbjZmcIndex))
                    print("发送切线用时：{}".format(time.time() - self.cbjSendLinesTime))
                    # 等待拖拽
                    while True:
                        if self.deviceStates.workStopFlag:
                            self.logger.debug("id_{} workStopFlag = True, 裁切机发送切线的任务函数退出".format(self.cbjZmcIndex))
                            return
                        ret, val = self.cbjZmc.get_drag_begin_state()
                        if ret != 0:
                            self.keep_zmc_read_write_error(ret, "cbjZmc", self.cbjZmcIndex)
                            return
                        if val == 1:
                            now = time.time()
                            if lastDragTime == 0:
                                dragBetween = 0
                                lastDragTime = now
                            else:
                                dragBetween = round(now - lastDragTime, 2)
                                lastDragTime = now
                            # 计算裁切长度和裁切面积,单位换算成米
                            cutLength = float(boardLine["cutDis"]) / 1000
                            cutAreas = float(boardLine["cutArea"]) / 1000 / 1000
                            self.logger.debug("id_{} 裁切机: 收到拖拽信号,两次拖拽间隔:{},裁切长度:{:.2f} m,裁切铜箔面积:{:.2f} ㎡".format(
                                self.cbjZmcIndex, dragBetween, cutLength, cutAreas))
                            self.boardKey = boardLine["key"]
                            if self.jointNumber == "4":
                                self.bigCutterZmcIndex = boardLine["cutterIndex"]
                                self.firstBoardLenBig = boardLine["firstBoardLenBig"]  # 大板总长
                                self.secondBoardLenBig = boardLine["secondBoardLenBig"]  # 大板单块
                                self.firstBoardLenSmall = boardLine["firstBoardLenSmall"]  # 一号小板单块
                                self.secondBoardLenSmall = boardLine["secondBoardLenSmall"]  # 一号小板总长
                                self.thirdBoardLenSmall = boardLine["thirdBoardLenSmall"]  # 二号小板单块
                                self.forthBoardLenSmall = boardLine["forthBoardLenSmall"]  # 二号小板总长
                                self.cutterTopMiddleAngle = boardLine["topMiddleAngle"]  # 上面大板与中缝的角度
                                self.cutterBottomMiddleAngle = boardLine["bottomMiddleAngle"]  # 下面大板与中缝的角度
                                self.leftMiddleAngleUp = boardLine["leftMiddleAngleUp"]  # 上左小板与中缝的角度
                                self.rightMiddleAngleUp = boardLine["rightMiddleAngleUp"]  # 上右小板与中缝的角度
                                self.leftMiddleAngleDown = boardLine["leftMiddleAngleDown"]  # 下左小板与中缝的角度
                                self.rightMiddleAngleDown = boardLine["rightMiddleAngleDown"]  # 下右小板与中缝的角度
                                self.horVerAngleUp = boardLine["horVerAngleUp"]
                                self.horVerAngleDown = boardLine["horVerAngleDown"]
                                self.cutterAngleOffsetUp = round(self.horVerAngleUp + self.twoCutterAngleOffset, 2)
                                self.cutterAngleOffsetDown = round(self.horVerAngleDown + self.twoCutterAngleOffset, 2)

                            elif self.jointNumber == "6":
                                self.bigCutterZmcIndex = boardLine["cutterIndex"]
                                self.firstBoardLenBig = boardLine["firstBoardLenBig"]
                                self.secondBoardLenBig = boardLine["secondBoardLenBig"]
                                self.thirdBoardLenBig = boardLine["thirdBoardLenBig"]

                                self.firstBoardLenSmall = boardLine["firstBoardLenSmall"]
                                self.secondBoardLenSmall = boardLine["secondBoardLenSmall"]
                                self.thirdBoardLenSmall = boardLine["thirdBoardLenSmall"]
                                self.forthBoardLenSmall = boardLine["forthBoardLenSmall"]
                                self.fifthBoardLenSmall = boardLine["fifthBoardLenSmall"]  # 新加的第三块板的长度
                                self.sixthBoardLenSmall = boardLine["sixthBoardLenSmall"]  # 新加的第三块的长度

                                self.cutterTopMiddleAngle = boardLine["topMiddleAngle"]
                                self.cutterBottomMiddleAngle = boardLine["bottomMiddleAngle"]
                                self.leftMiddleAngle01 = boardLine["leftMiddleAngle01"]
                                self.rightMiddleAngle01 = boardLine["rightMiddleAngle01"]
                                self.leftMiddleAngle02 = boardLine["leftMiddleAngle02"]
                                self.rightMiddleAngle02 = boardLine["rightMiddleAngle02"]
                                self.leftMiddleAngle03 = boardLine["leftMiddleAngle03"]
                                self.rightMiddleAngle03 = boardLine["rightMiddleAngle03"]
                                self.cutterHorVerAngleUp = boardLine["horVerAngleUp"]
                                self.twoMiddleAngle = boardLine["horVerAngleCenter"]
                                self.bottomMiddleAngle02 = boardLine["horVerAngleDown"]  # 底边和第二个中缝的夹角
                                self.cutterAngleOffset = round(self.cutterHorVerAngleUp + self.twoCutterAngleOffset, 2)
                                print(boardLine)
                            ret = self.cbjZmc.set_update_cutter_state_finish()
                            if ret != 0:
                                self.keep_zmc_read_write_error(ret, "cbjZmc", self.cbjZmcIndex)
                                return
                            else:
                                if self.jointNumber == '4':
                                    self.logger.debug("id_{} 裁切机:4拼板, 大铡刀数据更新完成".format(self.cbjZmcIndex))
                                    self.logger.debug("id_{} 大铡刀数据,第一块:{:.2f},第二块:{:.2f},topMid:{},bottomMid:{}".format(
                                        self.cbjZmcIndex, self.firstBoardLenBig, self.secondBoardLenBig,
                                        self.cutterTopMiddleAngle, self.cutterBottomMiddleAngle))
                                    self.logger.debug("id_{} 小铡刀数据,第一块:{:.2f},第二块:{:.2f},角度:({:.2f},{:.2f},{:.2f})".format(
                                        self.cbjZmcIndex, self.firstBoardLenSmall, self.secondBoardLenSmall, self.leftMiddleAngleUp,
                                        self.rightMiddleAngleUp, self.horVerAngleUp))
                                    self.logger.debug("id_{} 小铡刀数据,第三块:{:.2f},第四块:{:.2f},角度:({:.2f},{:.2f},{:.2f})".format(
                                        self.cbjZmcIndex, self.thirdBoardLenSmall, self.forthBoardLenSmall, self.leftMiddleAngleDown,
                                        self.rightMiddleAngleDown, self.horVerAngleDown))
                                    self.update_cut_info(self.boardKey, int(self.jointNumber), cutLength, cutAreas,
                                                         float(dragBetween / 60 / 60 / 24))
                                    break
                                else:
                                    self.logger.debug("id_{} 裁切机:6拼板, 大铡刀数据更新完成".format(self.cbjZmcIndex))
                                    self.logger.debug("id_{} 大铡刀数据,第一块:{:.2f},第二块:{:.2f},第三块:{:.2f},topMid:{},twoMid:{},bottomMid:{}".format(
                                        self.cbjZmcIndex, self.firstBoardLenBig, self.secondBoardLenBig, self.thirdBoardLenBig,
                                        self.cutterTopMiddleAngle, self.twoMiddleAngle, self.cutterBottomMiddleAngle))
                                    self.logger.debug("id_{} 小铡刀数据,第一块:{:.2f},第二块:{:.2f},角度:({:.2f},{:.2f},{:.2f})".format(
                                        self.cbjZmcIndex, self.firstBoardLenSmall, self.secondBoardLenSmall, self.leftMiddleAngle01,
                                        self.rightMiddleAngle01, self.cutterHorVerAngleUp))
                                    self.logger.debug("id_{} 小铡刀数据,第三块:{:.2f},第四块:{:.2f},角度:({:.2f},{:.2f},{:.2f})".format(
                                        self.cbjZmcIndex, self.thirdBoardLenSmall, self.forthBoardLenSmall, self.leftMiddleAngle02,
                                        self.rightMiddleAngle02, self.twoMiddleAngle))
                                    self.logger.debug("id_{} 小铡刀数据,第五块:{:.2f},第六块:{:.2f},角度:({:.2f},{:.2f},{:.2f})".format(
                                        self.cbjZmcIndex, self.fifthBoardLenSmall, self.sixthBoardLenSmall, self.leftMiddleAngle03,
                                        self.rightMiddleAngle03, self.bottomMiddleAngle02))
                                    self.update_cut_info(self.boardKey, int(self.jointNumber), cutLength, cutAreas,
                                                         float(dragBetween / 60 / 60 / 24))
                                    break
                        else:
                            gevent.sleep(0.05)
                            continue
                else:
                    gevent.sleep(0.5)
                    self.logger.debug("id_{} 裁切机: 收到发送切线的函数,切线队列为空".format(self.cbjZmcIndex))
            else:
                gevent.sleep(0.05)

    def cam_zmc_task(self):
        """
        上料监控任务开启,主要负责上料拍照以及和底层通信
        :return:
        """
        self.logger.debug("上料拍照任务函数开启.")
        imageFailedCount = 0
        self.firstCheckBoardLen1 = 0
        self.firstCheckBoardLen2 = 0
        self.firstCheckBoardLen3 = 0  # 六拼的时候有3块板
        self.autoReGetImageCount = 0  # 自动重拍的计数
        self.upLeftOffset = [0, 0, 0, 0]
        self.upRightOffset = [0, 0, 0, 0]
        self.downRightOffset = [0, 0, 0, 0]
        self.downLeftOffset = [0, 0, 0, 0]
        self.idleTimeStart = time.time()  # 上料拍照的空闲时间
        while True:
            if self.deviceStates.workStopFlag:
                self.logger.debug("id_{} workStopFlag = True, 上料拍照任务退出.".format(self.camZmcIndex))
                return
            if not self.isAllowGetImage:
                gevent.sleep(0.5)
                continue
            if self.waitBoardBack:
                gevent.sleep(0.5)
                continue

            # 1.等待允许拍照的信号
            ret, val = self.camZmc.get_allow_get_pic_state()
            if ret != 0:
                self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
            if val == 1:
                self.logger.debug("id_{} 上料: get modbusbit(15) = 1,准备拍照!".format(self.camZmcIndex))
                self.idleTimeStart = time.time()  # 重置上料拍照开始时间
                if ec.eapOnline:
                    ec.realStatusData.statusId = DeviceStatus.Run.name  # 将设备置位运行状态
                info = ""
                self.b = None
                self.b = {
                    "cutSpeed": self.cutSpeed
                }
                res, img = self.imageJoint.get_image_from_line_cam()
                if res != "ok":
                    self.lineImage = None
                    # 2.如果这里已经抓图图片失败了,就没有必要往前走了,直接写入日志,并进行重拍.
                    if imageFailedCount == 0:
                        self.logger.debug("id_{} 上料: 相机获取图片失败1次,重新打开相机并进行重拍: {}".format(self.camZmcIndex, res))
                        ret = self.camZmc.img_result_failed()
                        if ret != "0":
                            self.keep_zmc_read_write_error(ret, "cameraError", self.camZmcIndex)
                            return
                        self.imageJoint.re_start_line_camera()
                        imageFailedCount += 1
                        continue
                    else:
                        self.logger.debug("id_{} 上料: 相机获取失败2次,前端界面弹窗提示: {}".format(self.camZmcIndex, res))
                        imageFailedCount = 0
                        self.keep_zmc_read_write_error(res, "cameraError", self.camZmcIndex)
                        continue
                else:
                    if not self.reGetImageFlag and EapConfig.eapOnline:
                        # 如果不是重拍
                        try:
                            response = eap_request.request_job_count_report(JobCountType.In)
                            response_parse.parse_job_count_report_response(response)
                        except Exception as e:
                            logger.debug(str(e))
                    else:
                        self.reGetImageFlag = False
                    val = self.camZmc.get_opera_procedure_start()
                    print(val)
                    if val == 1:
                        save_fail_image(img, self.widthMm, self.heightMm)
                        self.logger.debug("上料： 机械手放料收板台！")
                        continue
                    self.lineImage = img
                    self.logger.debug("id_{} 上料: 相机获取图片OK".format(self.camZmcIndex))
                    imageFailedCount = 0
                    keepTime = time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime())
                    self.fileName = "{}--{}--w_{}--h_{}".format(self.camZmcIndex, keepTime, self.widthPix, self.heightPix)
                    # 3.如果是四拼板,先去检测物料的区域是否ok.
                    if self.jointNumber == "4":
                        totalBoardRes = check_total_board_is_ok(self.lineImage, self.totalHeightMax, self.totalHeightMin,
                                                                self.boardBreak, self.jointNumber)
                        checkRes, hintInfo, totalBoardBox, totalBoardNoAngle, totalBoardOffset, \
                            totalBoardThresWithAngle, totalBoardResWithAngle = totalBoardRes
                        self.totalBoardBox = totalBoardBox
                        self.totalBoardThres = totalBoardThresWithAngle
                        self.totalBoard = totalBoardNoAngle
                        self.totalBoardOffset = totalBoardOffset
                        # 物料检测通过
                        if checkRes == "ok":
                            self.logger.debug("id_{} 上料: 物料检测通过: {}".format(self.camZmcIndex, hintInfo))
                        elif (checkRes == "noBoard" or checkRes == "sensorPosError") and self.autoReGetImageCount < 1:
                            self.logger.debug("id_{} 上料: 物料检测未通过: {},自动重拍!".format(self.camZmcIndex, hintInfo))
                            self.re_get_image()
                            self.autoReGetImageCount += 1
                            save_totalboard_error_image(self.camZmcIndex, self.lineImage, totalBoardResWithAngle, self.jointNumber)
                            gevent.sleep(0.5)
                            continue
                        else:
                            # 物料检测未通过
                            self.logger.debug("id_{} 上料: 物料检测未通过: {}".format(self.camZmcIndex, hintInfo))
                            # 未通过之后,就要弹窗提示工人,人工确认,将未通过的图片保存起来
                            save_totalboard_error_image(self.camZmcIndex, self.lineImage, totalBoardResWithAngle, self.jointNumber)
                            totalBoardSend = self.get_web_show_image(self.lineImage, totalBoardCheckImage=True)
                            msgVal = {
                                "val": "totalBoardError",
                                "hintInfo": "id_{} 物料检测未通过: {}".format(self.camZmcIndex, hintInfo),
                                "totalBoardRes": totalBoardSend
                            }
                            send_produce_state_to_ui(msgVal)
                            # 如果是非首板,就要蜂鸣器叫和亮灯
                            if not self.isFirstBoard:
                                self.bigCutterZmc.open_buzzer_alarm()
                            # 等待界面上弹窗确认,怎么搞,是直接通过,还是重新拍照.
                            self.webModify = True  # 等待前端界面工人操作.
                            self.totalBoardIsOk = False  # 物料是不OK的,如果工单确认了OK,就直接进行下面的操作.
                            while self.webModify and not self.deviceStates.workStopFlag:
                                gevent.sleep(0.5)
                                continue
                            # 这里的弹窗,界面要显示几个按钮,板回退,停止,重新拍照,物料OK.
                            if not self.totalBoardIsOk:  # 如果没有点击物料OK,就继续循环进行检测,无论是点了板回退,还是重新拍照都一样
                                continue
                    elif self.jointNumber == "6":
                        totalBoardRes = check_total_board_is_ok(self.lineImage, self.totalHeightMax, self.totalHeightMin,
                                                                self.boardBreak, self.jointNumber)
                        checkRes, hintInfo, totalBoardBox, totalBoardNoAngle, totalBoardOffset, \
                            totalBoardThresWithAngle, totalBoardResWithAngle = totalBoardRes
                        self.totalBoardBox = totalBoardBox
                        self.totalBoardThres = totalBoardThresWithAngle
                        self.totalBoard = totalBoardNoAngle
                        self.totalBoardOffset = totalBoardOffset
                        # 物料检测通过
                        if checkRes == "ok":
                            self.logger.debug("id_{} 上料: 物料检测通过: {}".format(self.camZmcIndex, hintInfo))
                        elif (checkRes == "noBoard" or checkRes == "sensorPosError") and self.autoReGetImageCount < 1:
                            self.logger.debug("id_{} 上料: 物料检测未通过: {},自动重拍!".format(self.camZmcIndex, hintInfo))
                            self.re_get_image()
                            self.autoReGetImageCount += 1
                            save_totalboard_error_image(self.camZmcIndex, self.lineImage, totalBoardResWithAngle, self.jointNumber)
                            gevent.sleep(0.5)
                            continue
                        else:
                            # 物料检测未通过
                            self.logger.debug("id_{} 上料: 物料检测未通过: {}".format(self.camZmcIndex, hintInfo))
                            # 未通过之后,就要弹窗提示工人,人工确认,将未通过的图片保存起来
                            save_totalboard_error_image(self.camZmcIndex, self.lineImage, totalBoardResWithAngle, self.jointNumber)
                            totalBoardSend = self.get_web_show_image(self.lineImage, totalBoardCheckImage=True)
                            msgVal = {
                                "val": "totalBoardError",
                                "hintInfo": "id_{} 物料检测未通过: {}".format(self.camZmcIndex, hintInfo),
                                "totalBoardRes": totalBoardSend
                            }
                            send_produce_state_to_ui(msgVal)
                            # 如果是非首板,就要蜂鸣器叫和亮灯
                            if not self.isFirstBoard:
                                self.bigCutterZmc.open_buzzer_alarm()
                            # 等待界面上弹窗确认,怎么搞,是直接通过,还是重新拍照.
                            self.webModify = True  # 等待前端界面工人操作.
                            self.totalBoardIsOk = False  # 物料是不OK的,如果工单确认了OK,就直接进行下面的操作.
                            while self.webModify and not self.deviceStates.workStopFlag:
                                gevent.sleep(0.5)
                                continue
                            # 这里的弹窗,界面要显示几个按钮,板回退,停止,重新拍照,物料OK.
                            if not self.totalBoardIsOk:  # 如果没有点击物料OK,就继续循环进行检测,无论是点了板回退,还是重新拍照都一样
                                continue
                    self.autoReGetImageCount = 0
                    # 如果是第一块板
                    if self.isFirstBoard:
                        resFirst = "fail"
                        boardSizeList = []
                        boardResList = []
                        upBoard = None
                        if self.jointNumber == "4":
                            resFirst, boardSizeList, boardResList, upBoard = get_size_check_result_4p(self.lineImage, self.widthPix,
                                                                                                      self.heightPix, self.calcThresBig,
                                                                                                      self.totalBoardBox, self.totalBoard)
                        elif self.jointNumber == "6":
                            resFirst, boardSizeList, boardResList, upBoard = get_size_check_result_6p(self.lineImage, self.widthPix,
                                                                                                      self.heightPix, self.calcThresBig,
                                                                                                      self.totalBoardBox, self.totalBoard)
                        self.upBoard = upBoard
                        if resFirst == "ok":
                            self.boardSizeList = boardSizeList
                            self.boardResList = boardResList
                            self.sendIndex = 0
                            boardSend = self.get_web_show_image(self.boardResList[self.sendIndex])
                            msgVal = {
                                "val": "boardSizeCheck",
                                "boardRes": boardSend,
                                "boardSize": self.boardSizeList[self.sendIndex],
                                "inputSize": (self.widthMm, self.heightMm),
                                "boardCalcError": (round(self.boardSizeList[self.sendIndex][0] - self.widthMm, 2),
                                                   round(self.boardSizeList[self.sendIndex][1] - self.heightMm, 2))  # 误差
                            }
                            send_produce_state_to_ui(msgVal)
                            self.waitCheckBoardSize = True
                            self.sizeCheckOkBtnClick = False
                            while self.waitCheckBoardSize:
                                if self.sizeCheckOkBtnClick:
                                    self.waitCheckBoardSize = False
                                gevent.sleep(0.1)
                        # 进行人工标注尺寸的逻辑,handSize 尺寸的缩放比是前端发送过来的
                        else:
                            self.web_request_hand_inner_board_size()  # 弹窗人工标注内板尺寸框,这个时候也要灯盖前端人工标注.
                            self.waitHandLabelInnerBoard = True
                            while self.waitHandLabelInnerBoard:
                                gevent.sleep(0.1)

                    self.boxList = []
                    # 尺寸去人以后根据是几拼板,然后获取内框的位置信息
                    if self.jointNumber == "4":
                        res, info, boxList4p = get_boxes_4p(self.lineImage, self.widthPix, self.heightPix, self.calcThresBig, self.calcThresSmall,
                                                            self.totalBoardBox, self.totalBoard, self.upLeftOffset, self.upRightOffset,
                                                            self.downRightOffset, self.downLeftOffset, self.isFirstBoard)
                        self.boxList = boxList4p

                    if self.jointNumber == "6":
                        res, info, boxList6p = get_boxes_6p(self.lineImage, self.widthPix, self.heightPix, self.calcThresBig,
                                                            self.calcThresSmall, self.totalBoardBox, self.totalBoard)
                        self.boxList = boxList6p

                    if res:
                        # 如果识别成功:
                        if self.jointNumber == "4":
                            cutLinesRes = get_lines_with_boxes_4p(self.lineImage, self.totalBoardBox, self.totalBoardThres,
                                                                  self.boxList, self.transMtx, self.topPix, self.leftPix,
                                                                  self.bottomPix, self.rightPix, self.totalBoardOffset)
                            self.cutLines, self.imgCut, self.boardLengthList, self.angleList, \
                                self.cutLength, self.cutArea, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
                            if self.isFirstBoard:
                                self.logger.debug("id_{} 上料: 首板,识别成功,切线:{}".format(self.camZmcIndex, self.cutLines))
                            else:
                                self.logger.debug("id_{} 上料: 非首板,识别成功,切线:{}".format(self.camZmcIndex, self.cutLines))

                            for point in self.cutLines:
                                if point[0] > self.cbjLimitX or point[0] < 0 or (point[1]) > self.cbjLimitY or \
                                        point[1] < 0:
                                    res = "lineError"
                                    info = "切线超限,请确认裁切机X和Y的极限值是否正确!xLimit={},yLimit={}".format(self.cbjLimitX, self.cbjLimitY)
                                    self.logger.debug("id_{} 上料: {}".format(self.camZmcIndex, info))
                                    break
                        if self.jointNumber == "6":
                            cutLinesRes = get_lines_with_boxes_6p(self.lineImage, self.boxList, self.transMtx, self.topPix, self.leftPix,
                                                                  self.bottomPix, self.rightPix, self.totalBoardBox, self.totalBoard,
                                                                  self.totalBoardThres, self.totalBoardOffset)
                            res, self.cutLines, self.imgCut, self.cutLength, self.cutArea, \
                                self.boardLengthList, self.angleList, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
                            if self.isFirstBoard:
                                self.logger.debug("id_{} 上料: 首板,识别成功,切线:{}".format(self.camZmcIndex, self.cutLines))
                            else:
                                self.logger.debug("id_{} 上料: 非首板,识别成功,切线:{}".format(self.camZmcIndex, self.cutLines))

                            for point in self.cutLines:
                                if point[0] > self.cbjLimitX or point[0] < 0 or (point[1]) > self.cbjLimitY or \
                                        point[1] < 0:
                                    res = "lineError"
                                    info = "切线超限,请确认裁切机X和Y的极限值是否正确!xLimit={},yLimit={}".format(self.cbjLimitX, self.cbjLimitY)
                                    self.logger.debug("id_{} 上料: {}".format(self.camZmcIndex, info))
                                    break

                    if res == "error" or res == "lineError" or not res:
                        if res == "lineError":
                            imageSendLineError = self.get_web_show_image(self.imgCut)
                            msgVal = {
                                "val": "cutLineCheck",
                                "cutImage": imageSendLineError,
                                "cutInfo": info
                            }
                            save_cut_line_image(self.camZmcIndex, self.imgCut, self.widthPix, self.heightPix,
                                                jointNumber=self.jointNumber)
                        else:
                            imageSend = self.get_web_show_image(self.totalBoard)
                            # 计算缩放比例
                            labelSizePix = [self.widthPix // cp.sizeScale, self.heightPix // cp.sizeScale]
                            labelSizeMm = [self.widthMm, self.heightMm]
                            if self.jointNumber == "4":
                                msgVal = {
                                    "val": "handAnnotated",
                                    "totalBoard": imageSend,
                                    "labelSizeMm": labelSizeMm,
                                    "labelSizePix": labelSizePix,
                                    "cutInfo": info
                                }
                            else:
                                msgVal = {
                                    "val": "handSixAnnotated",
                                    "totalBoard": imageSend,
                                    "labelSizeMm": labelSizeMm,
                                    "labelSizePix": labelSizePix,
                                    "cutInfo": info
                                }
                        self.webModify = True
                        send_produce_state_to_ui(msgVal)
                        # 标注框的蜂鸣器叫和亮灯
                        self.bigCutterZmc.open_buzzer_alarm()
                        save_calc_error_image(self.camZmcIndex, self.lineImage, self.widthPix, self.heightPix,
                                              self.upLeftOffset, self.upRightOffset, self.downLeftOffset, self.downRightOffset, self.jointNumber)

                    elif res == "middleError":
                        imageSendMiddleError = self.get_web_show_image(self.imgCut)
                        info = "水平方向中缝错位太大,请把板子放到缓存台."
                        msgVal = {
                            "val": "middleErrorCheck",
                            "cutImage": imageSendMiddleError,
                            "cutInfo": info
                        }
                        self.webModify = True
                        send_produce_state_to_ui(msgVal)
                        self.bigCutterZmc.open_buzzer_alarm()
                        save_calc_error_image(self.camZmcIndex, self.lineImage, self.widthPix, self.heightPix,
                                              self.upLeftOffset, self.upRightOffset, self.downLeftOffset, self.downRightOffset, self.jointNumber)

                    else:
                        save_calc_ok_image(self.camZmcIndex, self.lineImage, self.widthPix, self.heightPix,
                                           self.upLeftOffset, self.upRightOffset, self.downLeftOffset, self.downRightOffset, jointNumber=self.jointNumber)
                        # if self.jointNumber == "2":
                        #     save_train_dataset(self.angleBox1, self.angleBox2, self.totalBoard, self.fileName)
                        if self.isFirstBoard:
                            self.webModify = True
                            imageSend = self.get_web_show_image(self.imgCut)
                            msgVal = {
                                "val": "cutLineCheck",
                                "cutImage": imageSend,
                                "cutInfo": info
                            }
                            send_produce_state_to_ui(msgVal)
                        else:
                            if self.jointNumber == "4":
                                firstHeight = self.boardLengthList[0]  # 第一块板长
                                secondHeight = self.boardLengthList[1]  # 第二块板长
                                firstBoardError = firstHeight - self.firstCheckBoardLen1
                                secondBoardError = secondHeight - self.firstCheckBoardLen2
                                totalBoardError = firstBoardError + secondBoardError
                                if abs(firstBoardError) > self.firstBoardErrorThres or abs(secondBoardError) > self.secondBoardErrorThres:
                                    info = 'id_{}  上料：和首板尺寸验证失败,弹窗提示确认切线是否OK.偏差值,第一块={:.2f},第二块={:.2f},总长偏差={:.2f}'.format(
                                        self.camZmcIndex, firstBoardError, secondBoardError, totalBoardError)
                                    self.logger.debug(info)
                                    imageSend = self.get_web_show_image(self.imgCut)
                                    msgVal = {
                                        "val": "cutLineCheck",
                                        "cutImage": imageSend,
                                        "cutInfo": info
                                    }
                                    self.bigCutterZmc.open_buzzer_alarm()
                                    send_produce_state_to_ui(msgVal)
                                    self.webModify = True
                                else:
                                    if self.jointNumber == "4":
                                        # self.keep_catch_pos() # 偏移补偿先去掉
                                        self.logger.debug('id_{} 上料：和首板尺寸验证通过.偏差值,第一块={:.2f},第二块={:.2f},总长偏差={:.2f}'.format(
                                            self.camZmcIndex, firstBoardError, secondBoardError, totalBoardError))
                                        self.b["boardIndex"] = self.camZmcIndex
                                        self.b["key"] = self.key
                                        self.b["firstPointX"] = self.cutLines[1][0]  # x坐标
                                        self.b["cutterIndex"] = self.camZmcIndex
                                        self.b["firstBoardLenBig"] = self.boardLengthList[0]
                                        self.b["secondBoardLenBig"] = self.boardLengthList[1]
                                        self.b["firstBoardLenSmall"] = self.boardLengthList[2]
                                        self.b["secondBoardLenSmall"] = self.boardLengthList[3]
                                        self.b["thirdBoardLenSmall"] = self.boardLengthList[4]
                                        self.b["forthBoardLenSmall"] = self.boardLengthList[5]
                                        self.b["topMiddleAngle"] = self.angleList[0]
                                        self.b["bottomMiddleAngle"] = self.angleList[1]
                                        self.b["cutDis"] = self.cutLength
                                        self.b["cutArea"] = self.cutArea
                                        self.b["cutWidth"] = self.cutWidth
                                        self.b["leftMiddleAngleUp"] = self.angleList[2]
                                        self.b["rightMiddleAngleUp"] = self.angleList[3]
                                        self.b["horVerAngleUp"] = self.angleList[4]
                                        self.b["leftMiddleAngleDown"] = self.angleList[5]
                                        self.b["rightMiddleAngleDown"] = self.angleList[6]
                                        self.b["horVerAngleDown"] = self.angleList[7]
                                        cutLines, knifeAngleList = self.change_cut_lines_order(self.cutLines)
                                        self.b["lines"] = cutLines
                                        self.b["knifeAngleList"] = knifeAngleList

                                    self.linesQueue.put(self.b)
                                    self.logger.debug("id_{} 上料: 切线存放到切线队列中,放入后切线队列个数 = {}".format(self.camZmcIndex,
                                                                                                                        self.linesQueue.qsize()))
                                    # self.keep_catch_pos()
                                    save_cut_line_image(self.camZmcIndex, self.imgCut, self.widthPix,
                                                        self.heightPix, jointNumber=self.jointNumber)
                                    ret = self.camZmc.img_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
                                        return ret
                                    self.camZmcIndex += 1
                                    if self.camZmcIndex > self.indexMax:
                                        self.camZmcIndex = 1
                                    newData = {
                                        "camZmcIndex": self.camZmcIndex,
                                        "cutId": self.prodId
                                    }
                                    self.update_working_info_to_db_and_web(newData)

                            elif self.jointNumber == "6":
                                firstBoardLen = self.boardLengthList[0]
                                secondBoardLen = self.boardLengthList[1]
                                thirdBoardLen = self.boardLengthList[2]
                                firstBoardError = firstBoardLen - self.firstCheckBoardLen1
                                secondBoardError = secondBoardLen - self.firstCheckBoardLen2
                                thirdBoardError = thirdBoardLen - self.firstCheckBoardLen3

                                if abs(firstBoardError) > self.firstBoardErrorThres or abs(secondBoardError) > self.firstBoardErrorThres or \
                                        abs(thirdBoardError) > self.secondBoardErrorThres:
                                    info = 'id_{}  上料：和首板尺寸验证失败,弹窗提示切线是否OK.第一块:{:.2f},第二块:{:.2f},第三块:{:.2f},总偏差:{:.2f}'.format(
                                        self.camZmcIndex, firstBoardError, secondBoardError, thirdBoardError,
                                        firstBoardError + secondBoardError + thirdBoardError)
                                    self.logger.debug(info)
                                    imageSend = self.get_web_show_image(self.imgCut)
                                    msgVal = {
                                        "val": "cutLineCheck",
                                        "cutImage": imageSend,
                                        "cutInfo": info
                                    }
                                    self.bigCutterZmc.open_buzzer_alarm()
                                    send_produce_state_to_ui(msgVal)
                                    self.webModify = True

                                else:
                                    self.b["boardIndex"] = self.camZmcIndex
                                    self.b["key"] = self.key
                                    self.b["firstPointX"] = self.cutLines[1][0]  # x坐标
                                    self.b["cutterIndex"] = self.camZmcIndex
                                    self.b["cutDis"] = self.cutLength
                                    self.b["cutArea"] = self.cutArea
                                    self.b["cutWidth"] = self.cutWidth
                                    self.b["firstBoardLenBig"] = self.boardLengthList[0]  # 第一块板长
                                    self.b["secondBoardLenBig"] = self.boardLengthList[1]  # 第二块板长
                                    self.b["thirdBoardLenBig"] = self.boardLengthList[2]  # 第三块板长
                                    self.b["firstBoardLenSmall"] = self.boardLengthList[3]  # 小板第一块
                                    self.b["secondBoardLenSmall"] = self.boardLengthList[4]
                                    self.b["thirdBoardLenSmall"] = self.boardLengthList[5]
                                    self.b["forthBoardLenSmall"] = self.boardLengthList[6]
                                    self.b["fifthBoardLenSmall"] = self.boardLengthList[7]
                                    self.b["sixthBoardLenSmall"] = self.boardLengthList[8]
                                    cutLines, knifeAngleList = self.change_cut_lines_order(self.cutLines)
                                    self.b["lines"] = cutLines
                                    self.b["knifeAngleList"] = knifeAngleList

                                    self.b["topMiddleAngle"] = self.angleList[0]
                                    self.b["bottomMiddleAngle"] = self.angleList[1]
                                    self.b["leftMiddleAngle01"] = self.angleList[2]
                                    self.b["rightMiddleAngle01"] = self.angleList[3]
                                    self.b["leftMiddleAngle02"] = self.angleList[4]
                                    self.b["rightMiddleAngle02"] = self.angleList[5]
                                    self.b["leftMiddleAngle03"] = self.angleList[6]
                                    self.b["rightMiddleAngle03"] = self.angleList[7]
                                    self.b["horVerAngleUp"] = self.angleList[8]
                                    self.b["horVerAngleCenter"] = self.angleList[9]
                                    self.b["horVerAngleDown"] = self.angleList[10]

                                    self.linesQueue.put(self.b)
                                    self.logger.debug("id_{} 上料: 切线存放到切线队列中,放入后切线队列个数 = {}".format(self.camZmcIndex,
                                                                                                                        self.linesQueue.qsize()))
                                    # self.keep_catch_pos()
                                    save_cut_line_image(self.camZmcIndex, self.imgCut, self.widthPix,
                                                        self.heightPix, jointNumber=self.jointNumber)
                                    ret = self.camZmc.img_result_ok()
                                    if ret != 0:
                                        self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
                                        return ret
                                    self.camZmcIndex += 1
                                    if self.camZmcIndex > self.indexMax:
                                        self.camZmcIndex = 1
                                    newData = {
                                        "camZmcIndex": self.camZmcIndex,
                                        "cutId": self.prodId
                                    }
                                    self.update_working_info_to_db_and_web(newData)

                    while self.webModify:
                        if self.deviceStates.workStopFlag:
                            self.logger.debug("id_{} workStopFlag = True,上料拍照任务退出!")
                            return
                        gevent.sleep(0.5)

            else:
                gevent.sleep(0.05)
                idleTime = time.time() - self.idleTimeStart
                if idleTime > int(ec.idleTime) and ec.eapOnline:
                    ec.realStatusData.statusId = DeviceStatus.Idle.name  # 将设备置位空闲状态
                continue

    @staticmethod
    def get_web_show_image(imageOriginal, totalBoardCheckImage=False):
        """
        将要发送给前端的原图,按照缩放比例,进行缩放,然后显示到前端
        :param imageOriginal: 要发送给前端显示的原图
        :param totalBoardCheckImage:是否发送的是物料区域检测的时候的原图,这个时候图比较大,按照1000的尺寸去搞定
        :return:
        """
        if totalBoardCheckImage:
            print("ImageOriginal = ({},{})".format(imageOriginal.shape[1], imageOriginal.shape[0]))
            h, w = imageOriginal.shape[:2]
            newWidth = 1000
            newHeight = int((h / w) * newWidth)
            imageSend = cv.resize(imageOriginal, (newWidth, newHeight), cv.INTER_AREA)
            imageSend = common_tools.image_to_string(imageSend)
            return imageSend
        print("ImageOriginal = ({},{})".format(imageOriginal.shape[1], imageOriginal.shape[0]))
        h, w = imageOriginal.shape[:2]
        newWidth, newHeight = int(w / cp.sizeScale), int(h / cp.sizeScale)
        imageSend = cv.resize(imageOriginal.copy(), (newWidth, newHeight), cv.INTER_AREA)
        print("boardSized = ({};{})".format(imageSend.shape[1], imageSend.shape[0]))
        imageSend = common_tools.image_to_string(imageSend)
        return imageSend

    def keep_catch_pos(self, offsetZeroFlag=False):
        """
        保存板宽以及求y轴补偿的逻辑,offsetZero=0表示按照0偏移去做补偿
        """
        if self.orderWidthMm > 1070:
            catchPosOffsetUsed = cp.catchPosOffsetBig
        else:
            catchPosOffsetUsed = cp.catchPosOffsetSmall
        # 抓板位置浮动值,没10块做一次浮动.
        if offsetZeroFlag:
            catchPosOffset = 0  # 加负号的原因是偏移的坐标和机械手的坐标是反的.
            catchPosRange = 30
        else:
            catchPosOffset = -catchPosOffsetUsed[self.camZmcIndex % 100 // 10]  # 加负号的原因是偏移的坐标和机械手的坐标是反的
            catchPosRange = cp.catchPosOffsetRange

        # 实际的写入值:
        catchPosRegLong = int(catchPosOffset + catchPosRange)
        catchPosRegRange = int(cp.catchPosOffsetRange)
        ret1 = self.camZmc.set_modbus_long(1000, 1, [catchPosRegLong])
        ret2 = self.camZmc.set_modbus_long(1002, 1, [catchPosRegRange])
        if ret1 != 0 and ret2 != 0:
            self.keep_zmc_read_write_error("上料控制器通信异常", "camZmc", self.camZmcIndex)
            return "error"
        self.logger.debug("id_{} 上料: 保存放板位置,以及板偏移成功!,抓板位置偏移值:{},写入值:{},偏移取值范围: {},物料宽:{}".format(
            self.camZmcIndex, catchPosOffset, catchPosRegLong, catchPosRegRange, self.orderWidthMm))

        self.cutYAxisOffset = -catchPosOffset  # 更新y轴的偏移值,y轴硬补偿1个mm

    def change_cut_lines_order(self, cutLines):
        """
        更改切线的顺序
        :param cutLines:切线列表
        :return:
        """
        # pList = cutLines[:8]
        # pList = [(p[0], round(p[1] + self.cutYAxisOffset, 2)) for p in pList]  # 将y的补偿加进来s
        # # 检测y坐标是否超过了极限,如果超过了极限,就按照0去做偏移,但是这个时候,底层的偏移值已经写了,所以要重新写一次偏移
        # for point in pList:
        #     if point[0] > self.cbjLimitX or point[0] < 0 or point[1] > self.cbjLimitY or \
        #             point[1] < 0:
        #         self.keep_catch_pos(offsetZeroFlag=True) # 将坐标的偏移再改回来
        #         pList = cutLines[:8] # 这里是将pList也替换回来

        p1, p2, p3, p4, p5, p6, p7, p8, *_ = cutLines
        newLines = []
        newAngleOffsetList = []
        if self.isFirstCut:
            newLines.append(p1)
            newLines.append(p2)
            newAngleOffsetList.append(cp.knifeAngleList[0])
        if self.leftPix != 0:
            newLines.append(p7)
            newLines.append(p8)
            newAngleOffsetList.append(cp.knifeAngleList[3])
        if self.isThirdCut:
            newLines.append(p3)
            newLines.append(p4)
            newAngleOffsetList.append(cp.knifeAngleList[2])
        if self.rightPix != 0:
            newLines.append(p5)
            newLines.append(p6)
            newAngleOffsetList.append(cp.knifeAngleList[1])
        return newLines, newAngleOffsetList

    def keep_order_calc_size(self):
        """
        保存工单做首板的时候确认的ok的尺寸信息
        :return:
        """
        self.widthMm = self.boardSizeList[self.sendIndex][0]
        self.heightMm = self.boardSizeList[self.sendIndex][1]
        self.widthPix = int(self.widthMm * cp.mm2pix)
        self.heightPix = int(self.heightMm * cp.mm2pix)
        try:
            newData = {
                "firstCheckWidth": self.widthMm,
                "firstCheckHeight": self.heightMm
            }
            res, info = self.db.update_order(self.key, newData)
            if res != "ok":
                errorInfo = "in keep_order_calc_size() error: {}".format(info)
                print(errorInfo)
                self.logger.debug(errorInfo)

        except Exception as e:
            errorInfo = "in keep_order_calc_size() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)

    def web_request_board_back(self):
        """
        前端界面点击了板回退
        :return:
        """
        # 关闭蜂鸣器报警
        self.bigCutterZmc.close_buzzer_alarm()
        ret = self.camZmc.img_result_failed()
        self.waitBoardBack = True  # 板回退,将等待板回退的标志位置为True,在点击重新拍照的时候再置为False
        self.webModify = False  # 将等待界面选择的搞掉
        self.logger.debug("id_{} 上料: 界面上点击了板回退,板退到拍照起点!".format(self.camZmcIndex))
        return "ok" if ret == 0 else ret

    def web_request_re_get_image(self):
        """
        界面上点击了重新拍照
        :return:
        """
        self.reGetImageFlag = True
        # 关闭蜂鸣器报警
        self.bigCutterZmc.close_buzzer_alarm()
        # 如果已经点击了板回退按钮,这个时候直接重拍就可以了.
        self.logger.debug("id_{} 上料: 界面上点击了重新拍照,进行重拍!".format(self.camZmcIndex))
        ret = 0
        if self.waitBoardBack:
            self.waitBoardBack = False
        else:
            ret = self.camZmc.img_result_failed()

        self.webModify = False
        self.camZmcIndex += 1
        if self.camZmcIndex > self.indexMax:
            self.camZmcIndex = 1
        newData = {
            "camZmcIndex": self.camZmcIndex
        }
        self.update_working_info_to_db_and_web(newData)
        return "ok" if ret == 0 else ret

    def update_cut_info(self, key, boardNumbers, cutDis, cutArea, tableUsed):
        """
        更新裁切机切割的相关参数,就是作业了多少个板的问题.第一个是要更新工单里面的数据,第二个要更新统计数据列表里面的数据.
        @param key:
        @param boardNumbers:
        @param cutDis:
        @param cutArea:
        @param tableUsed:
        @return:
        """
        # 先更新本工单的一些数据,先获取到本工单的数据,然后再进行更新.
        try:
            data = self.db.get_order_by_key(key)
            finished = data.get("finished")
            newData = {
                "finished": finished + boardNumbers
            }
            self.db.update_order(key, newData)
            # 更新基本信息的一些数据,包括裁切铜箔面积,已做板数量,还有台布使用时间.
            data = self.db.get_working_info()[1]
            knifeUsed = round(float(data.get("knifeUsed")) + cutDis, 4)
            cutAreas = round(float(data.get("cutAreas")) + cutArea, 4)
            cutAmounts = int(data.get("cutAmounts")) + boardNumbers
            tableUsed = round(float(data.get("tableUsed")) + tableUsed, 5)
            tableUsedDays = self.db.get_tableUsedDays()

            newData = {
                "knifeUsed": knifeUsed,
                "cutAreas": cutAreas,
                "cutAmounts": cutAmounts,
                "tableUsed": tableUsed,
                "tableUsedDays": tableUsedDays
            }
            self.db.save_working_info_data(newData)
            msgVal = {
                "val": self.key
            }
            send_order_state_to_ui(msgVal)
            self.logger.debug("id_{} 裁切机: 切割完成,基本信息和工单信息更新完成!".format(self.cbjZmcIndex))
            self.db.update_produce_record(boardNumbers)

        except Exception as e:
            errorInfo = "in update_cut_info() error : {}".format(str(e))
            self.logger.debug("id_{} {}".format(self.cbjZmcIndex, errorInfo))
            print(errorInfo)

    def update_working_info_to_db_and_web(self, newData):
        """
        更新workinfo的数据到数据库和前端
        :param newData: 新的数据值
        :return:
        """
        self.db.save_working_info_data(newData)
        send_working_info_state_to_ui()

    def web_request_total_board_is_ok(self):
        """
        界面上点击了物料确认ok
        :return:
        """
        # 关闭蜂鸣器叫和亮灯
        self.bigCutterZmc.close_buzzer_alarm()
        self.logger.debug("id_{} 上料: 界面上点击了物料检测确认OK,人工确认物料OK,继续作业!".format(self.camZmcIndex))
        self.totalBoardIsOk = True
        self.webModify = False

    def web_request_next_board_res(self):
        """
        前端界面点击了下一张.
        :return:
        """
        self.sendIndex += 1
        if self.sendIndex >= len(self.boardResList):
            self.sendIndex = 0
        boardSend = self.get_web_show_image(self.boardResList[self.sendIndex])
        msgVal = {
            "val": "boardSizeCheck",
            "boardRes": boardSend,
            "boardSize": self.boardSizeList[self.sendIndex],
            "inputSize": (self.widthMm, self.heightMm),
            "boardCalcError": (round(self.boardSizeList[self.sendIndex][0] - self.widthMm, 2),
                               round(self.boardSizeList[self.sendIndex][1] - self.heightMm, 2))  # 误差
        }
        send_produce_state_to_ui(msgVal)
        return "ok"

    def web_request_last_board_res(self):
        """
        前端界面点击了上一张
        :return:
        """
        self.sendIndex -= 1
        if self.sendIndex < 0:
            self.sendIndex = len(self.boardResList) - 1
        boardSend = self.get_web_show_image(self.boardResList[self.sendIndex])
        msgVal = {
            "val": "boardSizeCheck",
            "boardRes": boardSend,
            "boardSize": self.boardSizeList[self.sendIndex],
            "inputSize": (self.widthMm, self.heightMm),
            "boardCalcError": (round(self.boardSizeList[self.sendIndex][0] - self.widthMm, 2),
                               round(self.boardSizeList[self.sendIndex][1] - self.heightMm, 2))  # 误差
        }
        send_produce_state_to_ui(msgVal)

    def web_request_keep_ok_size(self):
        """
        前端界面上点击了确认尺寸OK
        :return:
        """
        self.logger.debug("id_{} 上料: 界面上点击了尺寸确认OK,保存识别使用尺寸,并保存图像".format(self.camZmcIndex))
        imageKeep = self.boardResList[self.sendIndex]
        self.keep_order_calc_size()
        if self.jointNumber == "6":
            self.calcThresBig = 20
            self.calcThresSmall = 15
        save_size_is_ok_image(self.camZmcIndex, imageKeep, self.widthPix, self.heightPix,
                              jointNumber=self.jointNumber)
        self.sizeCheckOkBtnClick = True

    @staticmethod
    def web_reqeust_test_new_function():
        """
        测试新的功能,测试新的功能,主要用来测试一些新功能,看看能否成功.
        :return:
        """
        # self.test_first_board_size_check()
        return "ok"

    def web_request_hand_inner_board_size(self):
        """
        界面上点击了人工标注.这个时候标注框,让人工去标注内板尺寸.
        :return:
        """
        boardSend = self.get_web_show_image(self.upBoard)
        labelSize = [self.widthPix // cp.sizeScale, self.heightPix // cp.sizeScale]
        labelSizeMm = [self.widthMm, self.heightMm]
        msgVal = {
            "val": "handBoardSize",
            "upBoardRes": boardSend,
            "labelBoardSize": labelSize,
            "labelBoardSizeMm": labelSizeMm
        }
        send_produce_state_to_ui(msgVal)
        return "ok"

    def web_request_adjust_board_size(self, adjustSize):
        """
        前端界面修改了标注的尺寸的按钮
        :return:
        """
        self.boardSizeAdjustFlag = True  # 是否调整了尺寸
        widthAdjust, heightAdjust = adjustSize
        widthOrignal, heightOriginal = self.widthMm, self.heightMm
        widthOrignal += widthAdjust
        heightOriginal += heightAdjust

        self.widthAdjustAfter = widthOrignal
        self.heightAdjustAfter = heightOriginal

        boardSend = self.get_web_show_image(self.upBoard)
        labelSize = [self.widthAdjustAfter * cp.mm2pix // cp.sizeScale, self.heightAdjustAfter * cp.mm2pix // cp.sizeScale]
        labelSizeMm = [self.widthAdjustAfter, self.heightAdjustAfter]
        msgVal = {
            "val": "handBoardSize",
            "upBoardRes": boardSend,
            "labelBoardSize": labelSize,
            "labelBoardSizeMm": labelSizeMm
        }
        send_produce_state_to_ui(msgVal)
        return "ok"

    def web_request_re_hand_label_two_boxes(self):
        """
        前端界面点击了重新标注
        :return:
        """
        # 关闭蜂鸣器叫和亮灯
        self.bigCutterZmc.close_buzzer_alarm()
        imageSend = self.get_web_show_image(self.totalBoard)
        # 计算缩放比例
        widthPix = (self.widthAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.widthPix
        heightPix = (self.heightAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.heightPix
        widthMm = (self.widthAdjustAfter if self.boardSizeAdjustFlag else self.widthMm)
        heightMm = (self.heightAdjustAfter if self.boardSizeAdjustFlag else self.heightMm)
        labelSizePix = [widthPix // cp.sizeScale, heightPix // cp.sizeScale]
        labelSizeMm = [widthMm, heightMm]
        info = "重新标注,请标注好内框位置,注意内框不含胶边,内框是内板和胶边的内边缘的分界点."
        if self.jointNumber == "4":
            msgVal = {
                "val": "handAnnotated",
                "totalBoard": imageSend,
                "labelSizeMm": labelSizeMm,
                "labelSizePix": labelSizePix,
                "cutInfo": info
            }
        else:
            msgVal = {
                "val": "handSixAnnotated",
                "totalBoard": imageSend,
                "labelSizeMm": labelSizeMm,
                "labelSizePix": labelSizePix,
                "cutInfo": info
            }

        send_produce_state_to_ui(msgVal)
        return "ok"

    def web_request_save_order(self, orderInfo):
        key = orderInfo["key"]
        if key == self.key:
            self.order_info_init(orderInfo)
        return self.db.web_request_save_order(orderInfo)

    def web_request_hand_label_four_boxes(self, boxInfo1, boxInfo2, boxInfo3, boxInfo4):
        """
        前端界面点击了标注,标注了两个内框位置
        :param boxInfo1: 标注的上框的位置信息和角度
        :param boxInfo2: 标注的下框的位置信息和角度
        :param boxInfo3: 标注的上框的位置信息和角度
        :param boxInfo4: 标注的下框的位置信息和角度
        :return:
        """
        # 关闭蜂鸣器叫和亮灯
        self.bigCutterZmc.close_buzzer_alarm()
        boxLeftTop1 = (np.array(boxInfo1[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop2 = (np.array(boxInfo2[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop3 = (np.array(boxInfo3[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop4 = (np.array(boxInfo4[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        if self.boardSizeAdjustFlag and self.isFirstBoard:
            self.widthMm = self.widthAdjustAfter
            self.heightMm = self.heightAdjustAfter
            self.widthPix = int(self.widthMm * cp.mm2pix)
            self.heightPix = int(self.heightMm * cp.mm2pix)
            newData = {
                "firstCheckWidth": self.widthMm,
                "firstCheckHeight": self.heightMm,
            }
            self.db.update_order(self.key, newData)

        box1 = self.get_box_rect_points(self.totalBoard, boxLeftTop1, boxInfo1[1])
        box2 = self.get_box_rect_points(self.totalBoard, boxLeftTop2, boxInfo2[1])
        box3 = self.get_box_rect_points(self.totalBoard, boxLeftTop3, boxInfo3[1])
        box4 = self.get_box_rect_points(self.totalBoard, boxLeftTop4, boxInfo4[1])
        assert box1 is not None
        assert box2 is not None
        assert box3 is not None
        assert box4 is not None
        self.boxList = [box1, box2, box4, box3]
        cutLinesRes = get_lines_with_boxes_4p(self.lineImage, self.totalBoardBox, self.totalBoardThres,
                                              self.boxList, self.transMtx, self.topPix, self.leftPix,
                                              self.bottomPix, self.rightPix, self.totalBoardOffset)
        self.cutLines, self.imgCut, self.boardLengthList, self.angleList, \
            self.cutLength, self.cutArea, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
        imageSend = self.get_web_show_image(self.imgCut)
        info = "获取切线OK,请确认切线位置是否正确."
        msgVal = {
            "val": "cutLineCheck",
            "cutImage": imageSend,
            "cutInfo": info
        }
        send_produce_state_to_ui(msgVal)
        self.logger.debug("id_ {} 上料: 界面上点击了标注,识别的切线结果: {}".format(self.camZmcIndex, self.cutLines))
        return "ok"

    def web_request_hand_label_six_boxes(self, boxInfo1, boxInfo2, boxInfo3, boxInfo4,
                                         boxInfo5, boxInfo6):
        """
        前端界面点击了标注,标注了六个内框位置
        :param boxInfo1: 标注的上框的位置信息和角度
        :param boxInfo2: 标注的下框的位置信息和角度
        :param boxInfo3: 标注的上框的位置信息和角度
        :param boxInfo4: 标注的下框的位置信息和角度
        :param boxInfo5:
        :param boxInfo6:
        :return:
        """
        # 关闭蜂鸣器叫和亮灯
        self.bigCutterZmc.close_buzzer_alarm()
        boxLeftTop1 = (np.array(boxInfo1[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop2 = (np.array(boxInfo2[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop3 = (np.array(boxInfo3[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop4 = (np.array(boxInfo4[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop5 = (np.array(boxInfo5[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        boxLeftTop6 = (np.array(boxInfo6[0]) * cp.sizeScale).astype('int').tolist()  # 转换为全部是int的列表
        if self.boardSizeAdjustFlag and self.isFirstBoard:
            self.widthMm = self.widthAdjustAfter
            self.heightMm = self.heightAdjustAfter
            self.widthPix = int(self.widthMm * cp.mm2pix)
            self.heightPix = int(self.heightMm * cp.mm2pix)
            newData = {
                "firstCheckWidth": self.widthMm,
                "firstCheckHeight": self.heightMm,
            }
            self.db.update_order(self.key, newData)

        box1 = self.get_box_rect_points(self.totalBoard, boxLeftTop1, boxInfo1[1])
        box2 = self.get_box_rect_points(self.totalBoard, boxLeftTop2, boxInfo2[1])
        box3 = self.get_box_rect_points(self.totalBoard, boxLeftTop3, boxInfo3[1])
        box4 = self.get_box_rect_points(self.totalBoard, boxLeftTop4, boxInfo4[1])
        box5 = self.get_box_rect_points(self.totalBoard, boxLeftTop5, boxInfo5[1])
        box6 = self.get_box_rect_points(self.totalBoard, boxLeftTop6, boxInfo6[1])
        assert box1 is not None
        assert box2 is not None
        assert box3 is not None
        assert box4 is not None
        assert box5 is not None
        assert box6 is not None
        self.boxList = [box1, box2, box3, box6, box5, box4]

        cutLinesRes = get_lines_with_boxes_6p(self.lineImage, self.boxList, self.transMtx, self.topPix, self.leftPix,
                                              self.bottomPix, self.rightPix, self.totalBoardBox, self.totalBoard,
                                              self.totalBoardThres, self.totalBoardOffset)
        # self.cutLines, self.imgCut, self.boardLengthList, self.angleList, \
        # self.cutLength, self.cutArea, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes

        res, self.cutLines, self.imgCut, self.cutLength, self.cutArea, \
            self.boardLengthList, self.angleList, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes

        imageSend = self.get_web_show_image(self.imgCut)
        info = "获取切线OK,请确认切线位置是否正确."
        msgVal = {
            "val": "cutLineCheck",
            "cutImage": imageSend,
            "cutInfo": info
        }
        send_produce_state_to_ui(msgVal)
        self.logger.debug("id_ {} 上料: 界面上点击了标注,识别的切线结果: {}".format(self.camZmcIndex, self.cutLines))
        return "ok"

    def web_request_adjust_board_size_two_box(self, adjustSize):
        """
        # 标注两个框的时候调整尺寸
        :param adjustSize: 调整的尺寸
        :return:
        """
        self.boardSizeAdjustFlag = True
        widthAdjust, heightAdjust = adjustSize
        widthOrignal, heightOriginal = self.widthMm, self.heightMm

        widthOrignal += widthAdjust
        heightOriginal += heightAdjust

        self.widthAdjustAfter = widthOrignal
        self.heightAdjustAfter = heightOriginal
        widthPix = (self.widthAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.widthPix
        heightPix = (self.heightAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.heightPix
        imageSend = self.get_web_show_image(self.totalBoard)
        labelSizePix = [widthPix // cp.sizeScale, heightPix // cp.sizeScale]

        msgVal = {
            "val": "handAnnotated",
            "labelSizeMm": [self.widthAdjustAfter, self.heightAdjustAfter],
            "totalBoard": imageSend,
            "labelSizePix": labelSizePix,
        }
        send_produce_state_to_ui(msgVal)
        return "ok"

    def get_box_rect_points(self, board, point, angle):
        """
        根据图像,以及左上角的点和角度获取标注的矩形
        :param board: 传递过来的整个物料框,矩形的左上角
        :param point: 最左边的点,angle,旋转角度
        :param angle:
        :return:
        """
        widthPix = int(self.widthAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.widthPix
        heightPix = int(self.heightAdjustAfter * cp.mm2pix) if self.boardSizeAdjustFlag else self.heightPix
        h, w = board.shape[:2]
        pointList = [[point[0] + widthPix, point[1]],
                     [point[0] + widthPix, point[1] + heightPix],
                     [point[0], point[1] + heightPix]]  # 矩形框的另外三个点
        newPoints = [point]  # 存放新的坐标点
        for p in pointList:
            x1 = p[0]
            y1 = h - p[1]
            x2 = point[0]
            y2 = h - point[1]
            x = int((x1 - x2) * np.cos(angle * np.pi / 180.0) - (y1 - y2) * np.sin(angle * np.pi / 180.0) + x2)
            y = int((x1 - x2) * np.sin(angle * np.pi / 180.0) + (y1 - y2) * np.cos(angle * np.pi / 180.0) + y2)
            y = h - y
            newPoints.append([x, y])
        return newPoints

    def web_request_hand_inner_board_size_is_ok(self, boardInfo):
        """
        界面上点击了标注内板尺寸,这个时候把这个标注的图保存到数据库.
        :param boardInfo:boardInfo,左上角的点,以及角度.
        :return:
        """
        self.logger.debug("id_{} 上料: 界面上点击了标注内板尺寸OK按钮.更新尺寸信息".format(self.camZmcIndex))
        self.waitHandLabelInnerBoard = False
        self.waitCheckBoardSize = False
        if self.boardSizeAdjustFlag:
            self.widthMm = self.widthAdjustAfter
            self.heightMm = self.heightAdjustAfter
            self.boardSizeAdjustFlag = False
        self.widthPix = int(self.widthMm * cp.mm2pix)
        self.heightPix = int(self.heightMm * cp.mm2pix)
        try:
            newData = {
                "firstCheckWidth": self.widthMm,
                "firstCheckHeight": self.heightMm
            }
            res, info = self.db.update_order(self.key, newData)
            if res != "ok":
                errorInfo = "in web_request_hand_inner_board_size_is_ok() error: {}".format(info)
                print(errorInfo)
                self.logger.debug(errorInfo)
        except Exception as e:
            errorInfo = "in web_request_hand_inner_board_size_is_ok() error: {}".format(str(e))
            print(errorInfo)
            self.logger.debug(errorInfo)

        leftTop, angle = boardInfo
        leftTop = [int(leftTop[0] * cp.sizeScale), int(leftTop[1] * cp.sizeScale)]
        upBoxPoints = self.get_box_rect_points(self.upBoard, leftTop, angle)
        keepImage = self.upBoard.copy()
        cv.drawContours(keepImage, [np.array(upBoxPoints)], -1, (0, 255, 255), 3)
        save_size_is_ok_image(self.camZmcIndex, keepImage, self.widthPix, self.heightPix, "handLabel", jointNumber=self.jointNumber)
        return "ok"

    def web_reqeust_cut_board(self, edgeRemainList):
        """
        界面上点击了切板
        :param edgeRemainList:界面上使用的留边宽度
        :return:
        """
        self.topMm, self.leftMm, self.bottomMm, self.rightMm = edgeRemainList
        self.topPix = int(self.topMm * cp.mm2pix)
        self.leftPix = int(self.leftMm * cp.mm2pix)
        self.bottomPix = int(self.bottomMm * cp.mm2pix)
        self.rightPix = int(self.rightMm * cp.mm2pix)
        self.bigCutterZmc.close_buzzer_alarm()  # 切板的时候将蜂鸣器关闭
        if self.isFirstBoard:
            if self.jointNumber == "4":
                self.firstCheckBoardLen1 = self.boardLengthList[0]
                self.firstCheckBoardLen2 = self.boardLengthList[1]
                self.logger.debug("id_{} 上料: 首板,4拼板,点击切板,首板尺寸值,第一块:{:.2f},第二块:{:.2f}".format(
                    self.camZmcIndex, self.firstCheckBoardLen1, self.firstCheckBoardLen2))
                # 然后将偏小阈值该为8
                self.calcThresSmall = 8
                self.calcThresBig = 20
            else:
                self.firstCheckBoardLen1 = self.boardLengthList[0]
                self.firstCheckBoardLen2 = self.boardLengthList[1]
                self.firstCheckBoardLen3 = self.boardLengthList[2]
                self.logger.debug("id_{} 上料: 首板,6拼板,点击切板,首板尺寸,第一块:{:.2f},第二块:{:.2f},第三块:{:.2f}".format(
                    self.camZmcIndex, self.firstCheckBoardLen1, self.firstCheckBoardLen2, self.firstCheckBoardLen3))
                # 然后将偏小阈值改为9
                self.calcThresSmall = 15
                self.calcThresBig = 20

        else:
            if self.jointNumber == "4":
                firstCheckBoardLen1 = self.boardLengthList[0]
                firstCheckBoardLen2 = self.boardLengthList[1]
                self.logger.debug("id_{} 上料: 非首板,6拼板,点击切板,当前尺寸,第一块:{:.2f},第二块:{:.2f}".format(
                    self.camZmcIndex, firstCheckBoardLen1, firstCheckBoardLen2))

            else:
                firstCheckBoardLen1 = self.boardLengthList[0]
                firstCheckBoardLen2 = self.boardLengthList[1]
                firstCheckBoardLen3 = self.boardLengthList[2]
                self.logger.debug("id_{} 上料: 非首板,6拼板,点击切板,当前尺寸,第一块:{:.2f},第二块:{:.2f},第三块:{:.2f}".format(
                    self.camZmcIndex, firstCheckBoardLen1, firstCheckBoardLen2, firstCheckBoardLen3))

        # 如果是首板点击了切板,要把四个切线的位置保存进去,并且重新保存识别成功的图.
        if self.isFirstBoard:
            if self.jointNumber == "4":
                self.upLeftOffset, self.upRightOffset, self.downLeftOffset, self.downRightOffset = get_line_offset_4p(self.boxList, self.totalBoard,
                                                                                                                      self.totalBoardBox)
                # 判断是否是长铜箔,并且把长铜箔加一个停板延时,长铜箔的判定目前暂定为100个mm,如果大于90个mm,如果大于90个mm就认为是长铜箔.
                if self.upLeftOffset[0] > cp.longCropperLimit * cp.mm2pix or self.upRightOffset[0] > cp.longCropperLimit * cp.mm2pix or \
                        self.downLeftOffset[2] > cp.longCropperLimit * cp.mm2pix or self.downRightOffset[2] > cp.longCropperLimit * cp.mm2pix:
                    isLongCropper = True
                else:
                    isLongCropper = False

                ret = self.camZmc.set_release_board_delay(isLongCropper)
                if ret != 0:
                    self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
                    return
                else:
                    self.logger.debug("id_{} 上料: 首板,4拼板,是否长铜箔: {} 设置成功,铜箔长度:({:.1f},{:.1f}),长铜箔阈值: {}".format(
                        self.camZmcIndex, isLongCropper, self.upLeftOffset[0], self.downLeftOffset[2], cp.longCropperLimit))

            else:
                # 六拼板判断是否是长铜箔的问题
                topOffset, rightOffset, bottomOffset, leftOffset = get_line_offset_6p(self.boxList, self.totalBoard, self.totalBoardBox)
                if max(topOffset, rightOffset, bottomOffset, leftOffset) > cp.longCropperLimit * cp.mm2pix:
                    isLongCropper = True
                else:
                    isLongCropper = False
                ret = self.camZmc.set_release_board_delay(isLongCropper)
                if ret != 0:
                    self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
                    return
                else:
                    self.logger.debug("id_{} 上料: 首板,6拼板,是否长铜箔: {} 设置成功,铜箔长度:({:.1f},{:.1f},{:.1f},{:.1f}),长铜箔阈值: {}".format(
                        self.camZmcIndex, isLongCropper, topOffset, rightOffset, bottomOffset, leftOffset, cp.longCropperLimit))
            save_calc_ok_image(self.camZmcIndex, self.lineImage, self.widthPix, self.heightPix, self.upLeftOffset, self.upRightOffset,
                               self.downLeftOffset, self.downRightOffset, jointNumber=self.jointNumber)
            save_first_board_cut_image(self.camZmcIndex, self.imgCut, self.widthPix, self.heightPix, endwith="first_cut",
                                       jointNumber=self.jointNumber)
            save_cut_line_image(self.camZmcIndex, self.imgCut, self.widthPix, self.heightPix,
                                jointNumber=self.jointNumber)
        else:
            save_cut_line_image(self.camZmcIndex, self.imgCut, self.widthPix, self.heightPix,
                                endwith="handLabel", jointNumber=self.jointNumber)

        # self.keep_catch_pos() # 偏移补偿先去除掉
        ret = self.camZmc.img_result_ok()
        if ret != 0:
            self.keep_zmc_read_write_error(ret, "camZmc", self.camZmcIndex)
            return ret
        if self.jointNumber == "4":

            # 切线顺序调换,将切线放入到队列中.
            self.b["boardIndex"] = self.camZmcIndex
            self.b["key"] = self.key
            self.b["firstPointX"] = self.cutLines[1][0]  # x坐标
            self.b["cutterIndex"] = self.camZmcIndex
            self.b["firstBoardLenBig"] = self.boardLengthList[0]
            self.b["secondBoardLenBig"] = self.boardLengthList[1]
            self.b["firstBoardLenSmall"] = self.boardLengthList[2]
            self.b["secondBoardLenSmall"] = self.boardLengthList[3]
            self.b["thirdBoardLenSmall"] = self.boardLengthList[4]
            self.b["forthBoardLenSmall"] = self.boardLengthList[5]
            self.b["topMiddleAngle"] = self.angleList[0]
            self.b["bottomMiddleAngle"] = self.angleList[1]
            self.b["cutDis"] = self.cutLength
            self.b["cutArea"] = self.cutArea
            self.b["cutWidth"] = self.cutWidth
            self.b["leftMiddleAngleUp"] = self.angleList[2]
            self.b["rightMiddleAngleUp"] = self.angleList[3]
            self.b["horVerAngleUp"] = self.angleList[4]
            self.b["leftMiddleAngleDown"] = self.angleList[5]
            self.b["rightMiddleAngleDown"] = self.angleList[6]
            self.b["horVerAngleDown"] = self.angleList[7]
            cutLines, knifeAngleList = self.change_cut_lines_order(self.cutLines)
            self.b["lines"] = cutLines
            self.b["knifeAngleList"] = knifeAngleList

            self.linesQueue.put(self.b)
            self.logger.debug("id_{} 上料: 切线存放到切线队列中,放入后切线队列个数 = {}".format(self.camZmcIndex,
                                                                                                self.linesQueue.qsize()))
        else:
            self.b["boardIndex"] = self.camZmcIndex
            self.b["key"] = self.key
            self.b["firstPointX"] = self.cutLines[1][0]  # x坐标
            self.b["cutterIndex"] = self.camZmcIndex
            self.b["cutDis"] = self.cutLength
            self.b["cutArea"] = self.cutArea
            self.b["cutWidth"] = self.cutWidth
            self.b["firstBoardLenBig"] = self.boardLengthList[0]  # 第一块板长
            self.b["secondBoardLenBig"] = self.boardLengthList[1]  # 第二块板长
            self.b["thirdBoardLenBig"] = self.boardLengthList[2]  # 第三块板长
            self.b["firstBoardLenSmall"] = self.boardLengthList[3]  # 小板第一块
            self.b["secondBoardLenSmall"] = self.boardLengthList[4]
            self.b["thirdBoardLenSmall"] = self.boardLengthList[5]
            self.b["forthBoardLenSmall"] = self.boardLengthList[6]
            self.b["fifthBoardLenSmall"] = self.boardLengthList[7]
            self.b["sixthBoardLenSmall"] = self.boardLengthList[8]
            self.change_cut_lines_order(self.cutLines)
            cutLines, knifeAngleList = self.change_cut_lines_order(self.cutLines)
            self.b["lines"] = cutLines
            self.b["knifeAngleList"] = knifeAngleList

            self.b["topMiddleAngle"] = self.angleList[0]
            self.b["bottomMiddleAngle"] = self.angleList[1]
            self.b["leftMiddleAngle01"] = self.angleList[2]
            self.b["rightMiddleAngle01"] = self.angleList[3]
            self.b["leftMiddleAngle02"] = self.angleList[4]
            self.b["rightMiddleAngle02"] = self.angleList[5]
            self.b["leftMiddleAngle03"] = self.angleList[6]
            self.b["rightMiddleAngle03"] = self.angleList[7]
            self.b["horVerAngleUp"] = self.angleList[8]
            self.b["horVerAngleCenter"] = self.angleList[9]
            self.b["horVerAngleDown"] = self.angleList[10]

            self.linesQueue.put(self.b)
            self.logger.debug("id_{} 上料: 切线存放到切线队列中,放入后切线队列个数 = {}".format(self.camZmcIndex,
                                                                                                self.linesQueue.qsize()))

        # 留边宽度更新到工单里面去
        newData = {
            "topEdge": self.topMm,
            "leftEdge": self.leftMm,
            "bottomEdge": self.bottomMm,
            "rightEdge": self.rightMm,
        }
        self.db.update_order(self.key, newData)
        self.db.web_request_get_order_by_key(self.key)
        self.webModify = False
        self.isFirstBoard = False
        self.camZmcIndex += 1
        if self.camZmcIndex > self.indexMax:
            self.camZmcIndex = 1
        newData = {
            "camZmcIndex": self.camZmcIndex,
            "cutId": self.prodId
        }
        self.update_working_info_to_db_and_web(newData)

    def web_reqeust_get_cut_lines_after_edge_change(self, edgeRemainList):
        """
        前端界面上调整了留边宽度
        :param edgeRemainList:留边宽度的列表,self.topEdge,self.leftEdge,self.bottomEdge,self.rightEdge
        :return:
        """
        edgeRemainListPix = [x * cp.mm2pix for x in edgeRemainList]
        topPix, leftPix, bottomPix, rightPix = edgeRemainListPix
        topMm, leftMm, bottomMm, rightMm = edgeRemainList
        if self.jointNumber == "4":
            cutLinesRes = get_lines_with_boxes_4p(self.lineImage, self.totalBoardBox, self.totalBoardThres,
                                                  self.boxList, self.transMtx, topPix, leftPix,
                                                  bottomPix, rightPix, self.totalBoardOffset)
            self.cutLines, self.imgCut, self.boardLengthList, self.angleList, \
                self.cutLength, self.cutArea, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes

            info = "识别成功"
            imageSend = self.get_web_show_image(self.imgCut)
            for point in self.cutLines:
                if point[0] > self.cbjLimitX or point[0] < 0 or point[1] > self.cbjLimitY or point[1] < 0:
                    info = "切线超限,请确认裁切机X和Y的极限值是否正确!xLimit={},yLimit={}".format(self.cbjLimitX, self.cbjLimitY)
                    self.logger.debug("id_{} {}".format(self.camZmcIndex, info))
                    return "error"
            msgVal = {
                "val": "cutLineCheck",
                "cutImage": imageSend,
                "cutInfo": info
            }
            send_produce_state_to_ui(msgVal)
            self.logger.debug("id_{} 上料: 手动调整留边宽度:top={},left={},bottom={},right={},结果: {}".format(self.camZmcIndex, topMm, leftMm,
                                                                                                               bottomMm, rightMm, info))
            return "ok"

        else:
            cutLinesRes = get_lines_with_boxes_6p(self.lineImage, self.boxList, self.transMtx, topPix, leftPix,
                                                  bottomPix, rightPix, self.totalBoardBox, self.totalBoard,
                                                  self.totalBoardThres, self.totalBoardOffset)
            res, self.cutLines, self.imgCut, self.cutLength, self.cutArea, \
                self.boardLengthList, self.angleList, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
            if res != "ok":
                res = "lineError"
                return res

            info = "识别成功"
            imageSend = self.get_web_show_image(self.imgCut)
            for point in self.cutLines:
                if point[0] > self.cbjLimitX or point[0] < 0 or point[1] > self.cbjLimitY or point[1] < 0:
                    info = "切线超限,请确认裁切机X和Y的极限值是否正确!xLimit={},yLimit={}".format(self.cbjLimitX, self.cbjLimitY)
                    self.logger.debug("id_{} {}".format(self.camZmcIndex, info))
                    return "error"
            msgVal = {
                "val": "cutLineCheck",
                "cutImage": imageSend,
                "cutInfo": info
            }
            send_produce_state_to_ui(msgVal)
            self.logger.debug("id_{} 上料: 手动调整留边宽度:top={},left={},bottom={},right={},结果: {}".format(self.camZmcIndex, topMm, leftMm,
                                                                                                               bottomMm, rightMm, info))
            return "ok"

        # else:
        #     cutLinesRes = get_lines_with_boxes_6p(self.lineImage, self.totalBoardBox, self.totalBoardThres,
        #                                           self.boxList, self.transMtx, topPix, leftPix,
        #                                           bottomPix, rightPix, self.totalBoardOffset)
        #     self.cutLines, self.imgCut, self.boardLengthList, self.angleList, \
        #     self.cutLength, self.cutArea, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
        #
        #     info = "识别成功"
        #     imageSend = self.get_web_show_image(self.imgCut)
        #     for point in self.cutLines:
        #         if point[0] > self.cbjLimitX or point[0] < 0 or point[1] > self.cbjLimitY or point[1] < 0:
        #             info = "切线超限,请确认裁切机X和Y的极限值是否正确!xLimit={},yLimit={}".format(self.cbjLimitX, self.cbjLimitY)
        #             self.logger.debug("id_{} {}".format(self.camZmcIndex, info))
        #             return "error"
        #     msgVal = {
        #         "val": "cutLineCheck",
        #         "cutImage": imageSend,
        #         "cutInfo": info
        #     }
        #     send_produce_state_to_ui(msgVal)
        #     self.logger.debug("id_{} 上料: 手动调整留边宽度:top={},left={},bottom={},right={},结果: {}".format(self.camZmcIndex, topMm, leftMm,
        #                                                                                            bottomMm, rightMm, info))
        #     return "ok"

    # def test_first_board_size_check(self):
    #     """
    #     测试首检弹框的逻辑.
    #     :return:
    #     """
    #     filePath = r"D:\jingwang_01\7150--N--087411--2021-04-06_13-41-15--w_2003--h_1722.bmp"
    #     imageTest = cv.imread(filePath, cv.IMREAD_GRAYSCALE)
    #     self.lineImage = imageTest
    #     self.widthPix, self.heightPix = get_width_height_by_image_name_4p(filePath)
    #     self.widthMm = round(self.widthPix / cp.mm2pix, 2)
    #     self.heightMm = round(self.heightPix / cp.mm2pix, 2)
    #     self.boardBreak = False
    #     self.totalHeightMax = 2000
    #     self.totalHeightMin = 1000
    #     self.calcThresBig = 20
    #     self.calcThresSmall = 20
    #     self.jointNumber = "2"
    #     self.transMtx = [
    #         [0, 1, 0],
    #         [1, 0, 0]
    #     ]
    #     self.topPix, self.leftPix, self.bottomPix, self.rightPix = [1, 1, 1, 1]
    #     checkRes, checkInfo, totalBoardBox, boardThres, totalBoardRes = check_total_board_is_ok(self.lineImage, self.boardBreak,
    #                                                                                             self.totalHeightMax,
    #                                                                                             self.totalHeightMin, self.jointNumber)
    #     self.totalBoardBox = totalBoardBox
    #     self.boardThres = boardThres
    #     print(checkInfo)
    #     resFirst, boardSizeList, boardResList, upBoard = get_size_check_result_4p(self.lineImage, self.widthPix,
    #                                                                               self.heightPix, self.totalBoardBox)
    #     self.upBoard = upBoard
    #     if resFirst == "ok":
    #         self.boardSizeList = boardSizeList
    #         self.boardResList = boardResList
    #         self.sendIndex = 0
    #         boardSend = self.get_web_show_image(self.boardResList[self.sendIndex])
    #         msgVal = {
    #             "val": "boardSizeCheck",
    #             "boardRes": boardSend,
    #             "boardSize": self.boardSizeList[self.sendIndex],
    #             "inputSize": (self.widthMm, self.heightMm),
    #             "boardCalcError": (round(self.boardSizeList[self.sendIndex][0] - self.widthMm, 2),
    #                                round(self.boardSizeList[self.sendIndex][1] - self.heightMm, 2))  # 误差
    #         }
    #         send_produce_state_to_ui(msgVal)
    #         self.waitCheckBoardSize = True
    #         self.sizeCheckOkBtnClick = False
    #         while self.waitCheckBoardSize:
    #             if self.sizeCheckOkBtnClick:
    #                 self.keep_order_calc_size()
    #                 self.waitCheckBoardSize = False
    #             gevent.sleep(0.1)
    #     # 进行人工标注尺寸的逻辑,handSize 尺寸的缩放比是前端发送过来的
    #     else:
    #         imageSend = self.get_web_show_image(self.upBoard)
    #         labelSize = [self.widthPix // cp.sizeScale, self.heightPix // cp.sizeScale]
    #         msgVal = {
    #             "val": "handBoardSizeState",
    #             "upBoardRes": imageSend,
    #             "labelBoardSize": labelSize,
    #         }
    #         send_produce_state_to_ui(msgVal)
    #
    #     res, info, angleBox1, ngleBox2, totalBoard, totalBoardThres = get_boxes_4(self.lineImage, self.widthPix, self.heightPix,
    #                                                                               self.calcThresBig, self.calcThresSmall,
    #                                                                               self.totalBoardBox, self.boardThres)
    #     self.totalBoard = totalBoard
    #     self.totalBoardThres = totalBoardThres
    #     self.angleBox1 = angleBox1
    #     self.angleBox2 = ngleBox2
    #     cutLinesRes = get_lines_with_boxes_4p(self.lineImage, self.totalBoard, self.totalBoardBox, self.totalBoardThres,
    #                                           self.angleBox1, self.angleBox2, self.transMtx, self.topPix, self.leftPix,
    #                                           self.bottomPix, self.rightPix)
    #
    #     self.cutLines, self.imgCut, self.cutDis, self.isFirstCut, self.isThirdCut, self.cutWidth = cutLinesRes
    #
    #     imageSend = self.get_web_show_image(self.totalBoard)
    #     labelSizePix = [self.widthPix // cp.sizeScale, self.heightPix // cp.sizeScale]
    #     labelSizeMm = [self.widthMm, self.heightMm]
    #     msgVal = {
    #         "val": "handAnnotated",
    #         "totalBoard": imageSend,
    #         "labelSizeMm": labelSizeMm,
    #         "labelSizePix": labelSizePix,
    #         "cutInfo": info
    #     }
    #     send_produce_state_to_ui(msgVal)

    def re_get_image(self):
        """
        计算出图片上的感应器位置与物料位置距离差距过大，重新拍照
        :return:
        """
        # 是否是重新拍照,如果是重新拍照就不增加jobCount
        self.reGetImageFlag = True
        # 如果已经点击了板回退按钮,这个时候直接重拍就可以了.
        ret = self.camZmc.img_result_failed()
        self.webModify = False
        self.camZmcIndex += 1
        if self.camZmcIndex > self.indexMax:
            self.camZmcIndex = 1
        newData = {
            "camZmcIndex": self.camZmcIndex
        }
        self.update_working_info_to_db_and_web(newData)
        return "ok" if ret == 0 else ret

    @staticmethod
    def open_cutter_final_check_dir():
        """
        打开终检原图目录
        :return:
        """
        return open_dir_by_file_path(CUTTER_RAW_BEGIN_RES_DIR_BIG)

    @staticmethod
    def open_cutter_final_res_dir():
        """
        打开终检结果目录
        :return:
        """
        return open_dir_by_file_path(CUTTER_RAW_FINAL_RES_DIR_BIG)

    def web_request_first_keep_ok_size(self):
        widthOffset = round(self.boardSizeList[self.sendIndex][0] - self.orderWidthMm, 2)
        heightOffset = round(self.boardSizeList[self.sendIndex][1] - self.orderHeightMm, 2)
        if cp.maxOrderSIzeErrorThres < widthOffset or widthOffset < cp.minOrderSIzeErrorThres or cp.maxOrderSIzeErrorThres < heightOffset or heightOffset < cp.minOrderSIzeErrorThres:
            info = "确认作业的 实际作业尺寸：{} 与 工单输入尺寸：{} 偏差较大，偏差阈值范围：{}，和工单输入尺寸相比 宽：{}， 高：{}；请认真确认是否要放弃本次操作，重新开始首板作业流程！".format(
                (self.boardSizeList[self.sendIndex]), (self.widthMm, self.heightMm), (cp.minOrderSIzeErrorThres, cp.maxOrderSIzeErrorThres),
                widthOffset, heightOffset)
            displayStatus = True
            self.logger.debug("id_{},{}".format(self.camZmcIndex, info))
            msgVal = {
                "val": "displayStatus",
                "displayStatus": displayStatus,
                "cutInfo": info
            }
            send_produce_state_to_ui(msgVal)
        else:
            self.web_request_keep_ok_size()

    def web_request_get_camera_ip(self):
        res, data = self.db.get_cam_IP_connect()
        cam1_Mbps = data.get('cam1').get('netIP')
        cam1_Ip = data.get('cam1').get('cameraIP')
        cam2_Mbps = data.get('cam2').get('netIP')
        cam2_Ip = data.get('cam2').get('cameraIP')
        cam3_Mbps = data.get('cam3').get('netIP')
        cam3_Ip = data.get('cam3').get('cameraIP')
        cutcam1_Mbps = data.get('cutCam1').get('netIP')
        cutcam1_Ip = data.get('cutCam1').get('cameraIP')
        cutcam2_Ip = data.get('cutCam2').get('cameraIP')
        cutcam3_Ip = data.get('cutCam3').get('cameraIP')
        cutcam4_Ip = data.get('cutCam4').get('cameraIP')
        return [{'cam1_Mbps': cam1_Mbps, "cam1_Ip": cam1_Ip, 'cam2_Mbps': cam2_Mbps, 'cam2_Ip': cam2_Ip, 'cam3_Mbps': cam3_Mbps, 'cam3_Ip': cam3_Ip,
                 'cutcam1_Mbps': cutcam1_Mbps, 'cutcam1_Ip': cutcam1_Ip, 'cutcam2_Ip': cutcam2_Ip, 'cutcam3_Ip': cutcam3_Ip,
                 'cutcam4_Ip': cutcam4_Ip}]

    def web_request_set_opera_procedure_start(self, operaProcedureStart):
        if operaProcedureStart:
            ret = self.camZmc.set_opera_produce_start(1)
        else:
            self.isFirstBoard = True  # 重新做首板
            ret = self.camZmc.set_opera_produce_start(0)
        return ret

    def web_request_put_board_to_cache(self):
        """
        界面上点击放板到缓存台
        :return:
        """
        self.logger.debug("id_{} 界面上点击了抓板到缓存台!".format(self.camZmcIndex))
        self.camZmcIndex += 1
        if self.camZmcIndex > self.indexMax:
            self.camZmcIndex = 1
        newData = {
            "camZmcIndex": self.camZmcIndex,
            "cutId": self.prodId
        }
        self.update_working_info_to_db_and_web(newData)
        self.webModify = False
        # 这里添加放到缓存台的逻辑
        ret = self.camZmc.set_opera_start(1)
        self.bigCutterZmc.close_buzzer_alarm()
        return ret

    def web_reqeust_clear_line_queue(self):
        """
        前端发送切线队列清空的逻辑,这里一般是因为设备上料出现了急停.
        :return:
        """
        self.logger.debug("检测到上料急停复位,切线队列重置为空")
        if self.linesQueue is not None:
            self.linesQueue = queue.Queue()

    def web_request_cut_deep(self):
        """
        界面调整下到深度
        :return:
        """
        res, knifeCutParams = self.db.get_knife_cut_params()
        if res != "ok":
            errorInfo = knifeCutParams
            print(errorInfo)
            self.logger.debug(errorInfo)
            return errorInfo
        else:
            self.cutDeep = knifeCutParams.get("cutDeep")
            if self.cutDeep is None:
                return "数据库中无数据"
            newData = {
                "cutDeep": self.cutDeep + 0.1
            }
            res, info = self.db.save_knife_cut_params(newData)
            return "ok" if res == "ok" else info


if __name__ == '__main__':
    ph = ProduceHandler(None, None, None, None, None, None, None, None)
    print(ph.web_request_get_camera_ip())
